Reputation: 101
Let's say I have two addresses:
I need to update the directional portion from Ne to NE. However, I don't want to update Newark to NEwark and the same for Netherland. I think I can find all the instances easy enough with this IF statement in a loop:
$testAddress = '123 Newark Road Ne'
if (($testAddress -clike '* Ne') -or ($testAddress -clike '* Ne *')){
#code to replace Ne
}
But how do I go about replacing it? I can't use a -creplace '* Ne', '* NE'. Finding the index of '* Ne' just gives me -1 so I don't think I can do anything with that. I'm sure there's an easy concept that I'm just not coming across.
Upvotes: 1
Views: 347
Reputation: 864
You can use Regular Expressions to replace a certain part of your input with something which is not possible in the substitution operand in a regex expression by design (like uppercasing in .NET) by using a MatchEvaluator
, which is constructed in PowerShell like a scriptblock.
With that MatchEvaluator you can manipulate the matched part like you want, hence you are not restricted to anything when it comes to manipulation.
Beginning with PowerShell 6 you can even use it directly with the -replace
and -creplace
operators.
PowerShell versions below 6 does not have this option, but it's still possible using the .NET Regex Replace Method [regex]::Replace()
with a MatchEvaluator.
$textToReplace = 'Ne 123 Newark Road Ne', '123 Newark Road Ne', '987 Ne Netherland Avenue'
foreach ($text in $textToReplace) {
# using a scriptblock as System.Text.RegularExpressions.MatchEvaluator
# the param() part is mandatory. Everything that follows is the return for that particular match
[regex]::Replace($text, '(?<!\w)Ne(?!\w)', { param($regexMatch) $regexMatch.Value.ToUpper() })
}
$textToReplace = 'Ne 123 Newark Road Ne', '123 Newark Road Ne', '987 Ne Netherland Avenue'
foreach ($text in $textToReplace) {
$text -creplace '(?<!\w)Ne(?!\w)', { $_.Value.toUpper() }
}
The pattern (?<!\w)Ne(?!\w)
matches all words Ne
for which the preceding and following character is not a word character using a negative lookbehind (?<!)
and negative lookahead (?!)
group construct.
\w
(Word) in .NET
includes all Unicode characters of the following categories:
MSFT: Character classes in regular expressions -> Word character: \w:
These include, but are not limited to:
a-z
and variants like è
A-Z
and variants like À
0-9
_
In short, \w
captures almost all word characters which are represented in the Unicode character set.
MSFT: Replacement with a script block in PS6+
Upvotes: 6
Reputation: 61068
Or use word boundaries around Ne
:
'123 Newark Road Ne','987 Ne Netherland Avenue' | ForEach-Object {
if ($_ -cmatch '(\bNe\b)') { $_ -creplace '(\bNe\b)', $Matches[1].ToUpper() }
else { $_ }
}
Output
123 Newark Road NE
987 NE Netherland Avenue
Upvotes: 0
Reputation: 60025
@('123 Newark Road Ne'
'987 Ne Netherland Avenue')|foreach{
switch -regex ($_)
{
'Ne$'{$_ -replace 'Ne$','NE'}
' Ne '{$_ -replace ' Ne ',' NE '}
Default {$_}
}
}
Upvotes: 0