0

Why is my regex pattern only returning the name/value of the first test ? I thought .+ would make it a non greedy pattern.

This is my code

$value = "Starting test: Connectivity
          Starting test: CheckSecurityError
          Starting test: DFSREvent"


$value -match 'Starting test: (?<testName>.+)' 

$matches.testName

This is my output

True
Connectivity
KingBain
  • 83
  • 10
  • 1
    If it's like other regex engines, dot doesn't match newlines unless you tell it to. Also the way you have it, the capturing group will include the seconds two "Starting test: " strings, as well as all the whitespace. – Dewi Morgan Jun 29 '17 at 15:16
  • What do you want it to return exactly? – Matt Jun 29 '17 at 16:32
  • Possible duplicate of [How to capture multiple regex matches, from a single line, into the $matches magic variable in Powershell?](https://stackoverflow.com/questions/3141851/how-to-capture-multiple-regex-matches-from-a-single-line-into-the-matches-mag) – TessellatingHeckler Jun 29 '17 at 17:17

3 Answers3

1
$value = @"
Starting test: Connectivity
Starting test: CheckSecurityError
Starting test: DFSREvent
"@

$Pattern = '^\s*Starting test: (?<testName>.+?)$'
($value -split '\n')|
    Where-Object {$_ -match $Pattern }|
      ForEach{$matches.testname}

"-----------------"
## alternative without named capture group

$value -split '\n' | 
  select-string -pattern  'Starting test: (.+)' -all | 
    ForEach {$_.matches.groups[1].value}

Sample output:

Connectivity
CheckSecurityError
DFSREvent
-----------------
Connectivity
CheckSecurityError
DFSREvent
1

One approach would be to use the .Net class, System.Text.RegularExpressions.Regex:

$value = "Starting test: Connectivity
          Starting test: CheckSecurityError
          Starting test: DFSREvent"
$regex = [System.Text.RegularExpressions.Regex]::new('Starting test: (?<testName>.+)')
$regex.Matches($value) | %{$_.Groups['testName'].value}

#or by calling the static method rather than instantiating a regex object:
#[System.Text.RegularExpressions.Regex]::Matches($value, 'Starting test: (?<testName>.+)') | %{$_.Groups['testName'].value}

Output

Connectivity
CheckSecurityError
DFSREvent

Or you can use Select-String as mentioned in other answers / only using %{$_.Groups['testName'].value to pull back the relevant capture groups' values from your matches.

$value | 
    select-string -Pattern 'Starting test: (?<testName>.+)' -AllMatches | 
    % Matches | 
    %{$_.Groups['testName'].value} 
Graham
  • 7,431
  • 18
  • 59
  • 84
JohnLBevan
  • 22,735
  • 13
  • 96
  • 178
0

You should use select-string:

$value -split '\n' | sls 'Starting test: (?<testName>.+)' | % { Write-Host 'Result' $_ }
majkinetor
  • 8,730
  • 9
  • 54
  • 72
  • How would i do this as a multi line regex ? – KingBain Jun 29 '17 at 15:29
  • Add the `-AllMatches` parameter on the `select-string` call. Not strictly `multi-line` in the regex definition (i.e. changing the behaviour of `^` and `$`, but it means it's able to return more than one match, which I think's what you're after. i.e. Acts as if the Global modifier were applied (https://www.w3schools.com/jsref/jsref_regexp_g.asp) – JohnLBevan Jun 29 '17 at 17:39