The Author Online Book Forums are Moving

The Author Online Book Forums will soon redirect to Manning's liveBook and liveVideo. All book forum content will migrate to liveBook's discussion forum and all video forum content will migrate to liveVideo. Log in to liveBook or liveVideo with your Manning credentials to join the discussion!

Thank you for your engagement in the AoF over the years! We look forward to offering you a more enhanced forum experience.

jeffreyr (2) [Avatar] Offline
#1
I love the ease with which one can use regex in PowerShell. However I've run into an error using a function with the -replace operator which I can't get around. Any thoughts...


*** Very brief overview ***
I want to call a function as part of a regex substitution. More specifically, I want to pass a regex match which is a number into a PowerShell custom function, have that function work with that match value and the return a substitution value. However something goes wrong if the function tries to convert the input parameter from a string to an integer.


*** Repro ***
Hopefully a simple repro will be easier to follow.

# define a very simple function to increment and return a value
function incrementNo ($match) {$substitutionValue = [int]$match + 1; $substitutionValue}

# this returns a conversion error
# (the $& is a regex code containing the match value)
'a1b' -replace 'd', $(incrementNo '$&')
Error Message = Cannot convert value "$&" to type "System.Int32". Error: "Input string was not in a correct format."


*** Notes ***
The above scenario works fine if the function doesn't try to convert the match parameter to an integer. For example:

# Define a function that does a simple string concatenation
function testFunction ($match) {$substitutionValue = "-" + $match + "-"; $substitutionValue}

# this works as expected
'a1b' -replace 'd', $(testFunction '$&')
a-1-b

So there appears to be something funky going on with the way PowerShell passes regex matches vai the function parameter which is interfering with the conversion operation.
//o// (5) [Avatar] Offline
#2
Re: Using functions w/ the regex -replace operator
Nice catch

PoSH> 'a1b' -replace 'd',('$0')
a1b

PoSH> 'a1b' -replace 'd',('$0' * 2)
a11b

PoSH> 'a1b' -replace 'd',([int]'$0' * 2)
Cannot convert value "$0" to type "System.Int32". Error: "Input string was not in a correct format."
At line:1 char:27
+ 'a1b' -replace 'd',([int] <<<< '$0' * 2)

PoSH> 'a1b' -replace 'd',(2 * '$0')
Cannot convert value "$0" to type "System.Int32". Error: "Input string was not in a correct format."
At line:1 char:25
+ 'a1b' -replace 'd',(2 * <<<< '$0')


PoSH> 'a1b' -replace 'd', $($a = '$0';[int]$a *2)
Cannot convert value "$0" to type "System.Int32". Error: "Input string was not in a correct format."
At line:1 char:41
+ 'a1b' -replace 'd', $($a = '$0';[int]$a <<<< *2)
ab
PoSH> 'a1b' -replace 'd', $($a = '$0';$a *2)
a11b

Seems resolving happens very late

PoSH> 'a1b' -replace 'd', $('$0' -match '1')
aFalseb
PoSH> 'a1b' -replace 'd', $('$0')
a1b

didn't find a good way to resove this as replacing with the -match function (way more ugly )

Greetings //o//
//o// (5) [Avatar] Offline
#3
Re: Using functions w/ the regex -replace operator
Think bruce did answer this Question before (In a bit other context) here :

http://blogs.msdn.com/powershell/archive/2006/07/25/678259.aspx

Problem is that the use a MatchEvaluator you need a delegate, what is not staightforward yet in PowerShell.

But with the script Bruce provided on the PowerShell Team blog you can make it work

As this is not so easy, there is a feature request on Connect to add scriptblock suport to the -replace operatator , by Keith Hill

Please vote this can help to get in into V2 of PowerShell

https://connect.microsoft.com/feedback/ViewFeedback.aspx?FeedbackID=264447&SiteID=99&wa=wsignin1.0

Greetings //o//



Greetings //o//
Kiron (38) [Avatar] Offline
#4
Re: Using functions w/ the regex -replace operator
# you could split the string in three groups, and increment the numeric group as you catenate them togerher:
$chrs1, [int]$num, $chrs2 =
('a1b' -replace '^(D+)(d+)(D+)$', '$1,$2,$3').split(',')
"$chrs1$($num + 1)$chrs2"

# ...or in a function:
function IncrementNumber ([string]$str, [int]$increment = 1) {
if ($str -notMatch '^D+d+D+$') {
write-error "$str does not fit pattern"
break
}
$chrs1, [int]$num, $chrs2 =
($str -replace '^(D+)(d+)(D+)$', '$1,$2,$3').split(',')
"$chrs1$($num + $increment)$chrs2"
}

# increment by 3
IncrementNumber a1b 3

# this errs because string does not fit the D+d+D+ pattern
IncrementNumber a1b4 4

# increment by 1 (default)
IncrementNumber a1b
jeffreyr (2) [Avatar] Offline
#5
Re: Using functions w/ the regex -replace operator
Thanks both of you for the suggestions smilie I've also added my vote and repo to the v2.0 feature request.