Powershell regex group : how do I get all subgroups 2

Viewed 55
3 Answers

Here is how you could do it using the call to Regex.Matches:

$data = @'
"C:\test\file1.txt"
"C:\test\file2.txt"
'@

$regex = [regex] '(.+\\)*(?<base>.+)\.(.+)'
$regex.Matches($data).ForEach{ $_.Groups['base'] }.Value

# Results in:
# file1
# file2

However since you're dealing with paths, I would personally recommend you to use FileInfo class to parse them. In this example, we can use the String .Trim(Char) Method to remove the leading and trailing " from each path and the -as Type Operator to safely convert the strings into System.IO.FileInfo instances.

$data = (@'
"C:\test\file1.txt"
"C:\test\file2.txt"
'@ -split '\r?\n').Trim('"') -as [IO.FileInfo[]]

$data.BaseName

An example of using -match and the $matches automatic variable to retrieve capture group values:

$data = @'
"C:\test\file1.txt"
"C:\test\file2.txt"
'@

$data -match '\\([^.\\]+)\.[\s\S]+?\\([^.\\]+)\.'

write-host $matches[1]    # file1
write-host $matches[2]    # file2

Just for completeness another RegEx solution:

$data = @'
"C:\te.st\file1.txt"
"C:/test/file2.foo.txt"
'@

[regex]::Matches($data, '[^\\/]+(?=\.[^\\/]+\")').Value

Output:

file1
file2.foo

The RegEx uses a positive lookahead (?=) to assert that an extension follows, without capturing it.

Detailed explanation at regex101.

I still think that the FileInfo solution is more robust and easier to maintain. It took me much longer to get the RegEx right than simply splitting and converting to FileInfo would have taken.

Related