如何从Select-String中获取捕获的组?

wat*_*ery 46 regex powershell select-string select-object

我正在尝试使用Powershell(版本4)从Windows上的一组文件中提取文本:

PS > Select-String -AllMatches -Pattern <mypattern-with(capture)> -Path file.jsp | Format-Table
Run Code Online (Sandbox Code Playgroud)

到现在为止还挺好.这给出了一组很好的MatchInfo对象:

IgnoreCase                    LineNumber Line                          Filename                      Pattern                       Matches
----------                    ---------- ----                          --------                      -------                       -------
    True                            30   ...                           file.jsp                      ...                           {...}
Run Code Online (Sandbox Code Playgroud)

接下来,我看到捕获是在匹配成员中,所以我把它们拿出来:

PS > Select-String -AllMatches -Pattern <mypattern-with(capture)> -Path file.jsp | ForEach-Object -MemberName Matches | Format-Table
Run Code Online (Sandbox Code Playgroud)

这使:

Groups        Success Captures                 Index     Length Value
------        ------- --------                 -----     ------ -----
{...}         True    {...}                    49        47     ...
Run Code Online (Sandbox Code Playgroud)

或作为列表| Format-List:

Groups   : {matched text, captured group}
Success  : True
Captures : {matched text}
Index    : 39
Length   : 33
Value    : matched text
Run Code Online (Sandbox Code Playgroud)

这是我停下来的地方,我不知道如何进一步获取捕获的组元素列表.

我试过添加另一个| ForEach-Object -MemberName Groups,但它似乎返回与上面相同.

我得到的最接近的是| Select-Object -Property Groups,这确实给了我期望的东西(套装列表):

Groups
------
{matched text, captured group}
{matched text, captured group}
...
Run Code Online (Sandbox Code Playgroud)

但是后来我无法从他们每个人中提取捕获的组,我试着| Select-Object -Index 1只得到其中一组.


更新:可能的解决方案

似乎通过添加| ForEach-Object { $_.Groups.Groups[1].Value }我得到了我正在寻找的东西,但我不明白为什么 - 所以我无法确定在将此方法扩展到整个文件集时我能够得到正确的结果.

它为什么有效?

作为旁注,这| ForEach-Object { $_.Groups[1].Value }(即没有第二个.Groups)给出了相同的结果.

我想补充一点,经过进一步的尝试,似乎可以通过删除管道来缩短命令| Select-Object -Property Groups.

JPB*_*anc 51

看看下面的内容

$a = "http://192.168.3.114:8080/compierews/" | Select-String -Pattern '^http://(.*):8080/(.*)/$' 
Run Code Online (Sandbox Code Playgroud)

$a现在是一个MatchInfo($a.gettype())它包含一个Matches属性.

PS ps:\> $a.Matches
Groups   : {http://192.168.3.114:8080/compierews/, 192.168.3.114, compierews}
Success  : True
Captures : {http://192.168.3.114:8080/compierews/}
Index    : 0
Length   : 37
Value    : http://192.168.3.114:8080/compierews/
Run Code Online (Sandbox Code Playgroud)

在小组成员中,你会找到你想要的东西,所以你可以写:

"http://192.168.3.114:8080/compierews/" | Select-String -Pattern '^http://(.*):8080/(.*)/$'  | % {"IP is $($_.matches.groups[1]) and path is $($_.matches.groups[2])"}

IP is 192.168.3.114 and path is compierews
Run Code Online (Sandbox Code Playgroud)

  • `%` 是 `ForEach-Object` 的别名。然后你可以用`$_`处理每个对象。 (4认同)

Kyl*_*Mit 10

根据正则表达式 > 组、捕获和替换上的 powershell 文档:

使用-match操作符时,powershell 会创建一个名为的自动变量$Matches

PS> "The last logged on user was CONTOSO\jsmith" -match "(.+was )(.+)"
Run Code Online (Sandbox Code Playgroud)

此表达式返回的值只是true| false, 但 PS 会添加$Matches 哈希表

因此,如果您输出$Matches,您将获得所有捕获组:

PS> $Matches

Name     Value
----     -----
2        CONTOSO\jsmith
1        The last logged on user was
0        The last logged on user was CONTOSO\jsmith
Run Code Online (Sandbox Code Playgroud)

您可以使用点符号单独访问每个捕获组,如下所示:

PS> "The last logged on user was CONTOSO\jsmith" -match "(.+was )(.+)"
PS> $Matches.2
CONTOSO\jsmith
Run Code Online (Sandbox Code Playgroud)

其他资源


Ped*_*ito 9

迟到的答案,但为了循环多个匹配和组,我使用:

$pattern = "Login:\s*([^\s]+)\s*Password:\s*([^\s]+)\s*"
$matches = [regex]::Matches($input_string, $pattern)

foreach ($match in $matches)
{
    Write-Host  $match.Groups[1].Value
    Write-Host  $match.Groups[2].Value
}
Run Code Online (Sandbox Code Playgroud)


Jer*_*her 7

这适合我的情况。

使用该文件:__test.txt__

// autogenerated by script
char VERSION[21] = "ABCDEFGHIJKLMNOPQRST";
char NUMBER[16] = "123456789012345";
Run Code Online (Sandbox Code Playgroud)

从文件中获取编号和版本。

PS C:\> Select-String -Path test.txt -Pattern 'VERSION\[\d+\]\s=\s\"(.*)\"' | %{$_.Matches.Groups[1].value}

ABCDEFGHIJKLMNOPQRST

PS C:\> Select-String -Path test.txt -Pattern 'NUMBER\[\d+\]\s=\s\"(.*)\"' | %{$_.Matches.Groups[1].value}

123456789012345
Run Code Online (Sandbox Code Playgroud)