0

I have a Match[] from string matching, each Match has a Groups property which is a GroupCollection. I want to map the Match[] to a GroupCollection[], and I'm trying to do this with a pipeline's output using ForEach-Object.

The issue is that whenever I access and return Match[x].Groups in the script block, the collection gets enumerated and outputted as its contents, essentially expanding and flattening the GroupCollection's and losing any instance properties.

Is there a way to pull this off with an pipeline output? Maybe ForEach-Object isn't the right function to use.

$String = "12345"
$Regex = "(?<number>\d)"
$MatchArr = ($String | Select-String  -Pattern $Regex -AllMatches).Matches # Match[]

$DesiredOutput = $MatchArr[0].Groups, $MatchArr[1].Groups, $MatchArr[2].Groups # etc..
Get-Member -InputObject $DesiredOutput[0] # "GroupCollection" 

$WrongOutput = $MatchArr | ForEach-Object {$_.Groups} # Resolves and outputs the collection contents, making a flat array of all the contents
Get-Member -InputObject $WrongOutput[0] # "Match"  $WrongOutput[0] == $MatchArr[0].Groups[0], AKA the actual contents
Brother58697
  • 2,290
  • 2
  • 4
  • 12

1 Answers1

0

While writing the question and including an iterative solution involving appending the collections to an array (still too long), the collections were still being enumerated when appended with +=, leading me down a search where I came across that problem's solution here, which can also be adapted to the original ForEach-Object pipeline.

The solution is to wrap the collection in an array which then gets resolved and enumerated instead, returning the collection itself. To create an array from an array, we need to use the comma operator. (Article linked in the SO answer I found).

$String = "12345"
$Regex = "(?<number>\d)"
$MatchArr = ($String | Select-String  -Pattern $Regex -AllMatches).Matches # Match[]

$Groups = $MatchArr | ForEach-Object {,$_.Groups}
Get-Member -InputObject $Groups[0] # "GroupCollection", Nice
Brother58697
  • 2,290
  • 2
  • 4
  • 12