Reputation: 883
The example is:
$testLines = "050 BLACK Michael Douglas 32 Kellogs Court Wondertown Fitter","056 WHITE Brian Dennis 101 Wood Street Wondertown Court Worker"
# hash table for linking a street type to the street name using an underscore
$streetTypeHash = @{
' Drive ' = '_Drive, ';
' Street ' = '_Street, ';
' Court Worker ' = ' Court Worker '; # include any term that may be mistakenly referenced. Ensure it remains unchanged.
' Court ' = '_Court, ';
}
# read the street type (e.g Street, Road, Drive, Court etc) & join with underscore to street name
for ($i = 0; $i -lt $testLines.Count; $i++) {
foreach ($Key in $streetTypeHash.Keys) {
if ($testLines[$i] -match $Key) {
$testLines[$i] = $testLines[$i] -replace $Key, $($streetTypeHash[$Key])
}
}
$testLines[$i]
The second line of output shows the problem:
050 BLACK Michael Douglas 32 Kellogs_Court, Wondertown Fitter
056 WHITE Brian Dennis 101 Wood_Street, Wondertown_Court, Worker
My understanding is: the first available match is 'Court'. Regardless of whether any other characters are part of the key string. Therefore it is not possible to use this approach to negate false matches. I have tried using another hash table:
$notStreetTypeHash = @{
' Court Worker ' = ' Court Worker ';
}
But using the respective keys, of these two hash tables, to find -match
& -notMatch
was not working.
Any suggestion appreciated.
Upvotes: 2
Views: 65
Reputation: 23673
So far I can tell, you where actually on the right way using a dictionary for what you trying to do. Yet the keys for either the -match
or -replace
operators should be more in a regular expression format as @Santiago points out in his helpful answer.
As e.g. ' Drive '
could be better surrounded by word bounderies than spaces (as that will also include e.g. an end-of-line): '\bDrive\b'
.
And as you found out yourself you can't include the exception in your keys, because the general design here works as an OR
operator: if the pattern matches Drive
OR Street
OR Court
then replace it. Meaning that your exception needs to be a part of the concerned regular expression: if Drive
OR Street
OR (Court
AND not Court Worker
) then .... You might do that with e.g. a look ahead regular expression:
$streetTypeHash = @{
'\bDrive\b' = '_Drive, '
'\bStreet\b' = '_Street, '
'\bCourt\s+(?!Worker)\b' = '_Court, ' # Court, but not Court Worker
}
foreach ($Line in $testLines) {
$streetTypeHash.Keys |ForEach-Object {
$Line = $Line -Replace $_, $streetTypeHash[$_]\
}
$Line
}
Upvotes: 1
Reputation: 60110
If I'm understanding correctly, you could just simplify the whole process to:
$testLines = @(
"050 BLACK Michael Douglas 32 Kellogs Court Wondertown Fitter"
"056 WHITE Brian Dennis 101 Wood Street Wondertown Court Worker"
)
$testLines -replace '\s(Drive|Street|Court)\s(?!Worker)', '_$1, '
See https://regex101.com/r/6S10JI/1 for details.
Upvotes: 3