Regular expression matching in PowerShell

后端 未结 5 815
野性不改
野性不改 2021-01-01 13:41

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

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

I\'m interested in

相关标签:
5条回答
  • 2021-01-01 13:52

    Just use -replace:

    $foo = 'abcDEF'
    $myMatch = "^abc(.*)"
    $myVar = $foo -replace $myMatch,'$1'
    #$myVar contains DEF
    
    0 讨论(0)
  • 2021-01-01 13:53

    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.

    0 讨论(0)
  • 2021-01-01 14:01

    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
    
    0 讨论(0)
  • 2021-01-01 14:04

    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.

    0 讨论(0)
  • 2021-01-01 14:10

    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]
    
    0 讨论(0)
提交回复
热议问题