ted
ted

Reputation: 2355

Regular expression matching in PowerShell

Is there an elegant one-liner for doing the following?

$myMatch = "^abc(.*)"
$foo -match $myMatch
$myVar = $matches[1]

I'm interested in the $myVar variable...

Upvotes: 24

Views: 41731

Answers (5)

asmoore82
asmoore82

Reputation: 156

Wrap it in a function.

This is almost always the correct answer if you are already happy with and understand a working solution but need it to be shorter. If the function is named properly it also begins to produce self-documenting and re-usable code. What could possibly be better?

Even if you are sure that there is a more elegant or efficient solution out there to find - you can still make it a function call first and then if the other solution comes along, you only have to change it in one place - the function definition itself. You can even then plug in and out different options to test reliability head to head for all of your use cases. What could possibly be better?

Others may complain about function call overhead but this is really neither the right stage of development nor the right type or programming language to worry about it. Debugging a failed attempt at a "cute" one-liner down the road will always outweigh the cost of a nice, clean function call. Good decisions now about clean function call API's can later turn functions into class methods and the classes themselves can seamlessly wrap high level caching and optimization techniques. Lower level optimization of function calls should be left to the lower level languages.

Upvotes: 0

JPBlanc
JPBlanc

Reputation: 72680

I am not sure about the elegance, but here is something useful:

PS > "123.134" -match "(?<P1>[0-9]{3})\.(?<P2>[0-9]{3})"
True
PS > $Matches

Name                           Value
----                           -----
P2                             134
P1                             123
0                              123.134


PS > $Matches["P1"]
123

?<P1> gives the label P1 to the first capture. It helps to understand.

PS > ([regex]("(?<P1>[0-9]{3})\.(?<P2>[0-9]{3})")).matches("123.123")[0].groups["P1"].value
123

In your case:

PS > $foo = "123.143"
PS > ([regex]("(?<P1>[0-9]{3})\.(?<P2>[0-9]{3})")).matches($foo)[0].groups["P1"].value
123
PS > ([regex]("(?<P1>[0-9]{3})\.(?<P2>[0-9]{3})")).matches($foo)[0].groups["P2"].value
143

Upvotes: 4

Daniel Richnak
Daniel Richnak

Reputation: 1604

I use something like the following pretty often:

([regex]"^abc(.*)").match($foo).groups[1].value

It's not very PowerShell-y, or at least not very PowerShell V2-y (we're falling back onto the .NET class)... but it's pretty compact.

Upvotes: 19

stej
stej

Reputation: 29479

Just use -replace:

$foo = 'abcDEF'
$myMatch = "^abc(.*)"
$myVar = $foo -replace $myMatch,'$1'
#$myVar contains DEF

Upvotes: 24

Emiliano Poggi
Emiliano Poggi

Reputation: 24846

Changed answer after clarification:

True one-liner:

$myvar = ($foo | ? {$_ -match $myMatch} | select @{L="Matches";E={$matches[1]}}).matches

Fake one-liner:

$foo | ? {$_ -match $myMatch} ; $myvar = $matches[1]

Upvotes: 4

Related Questions