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



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

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

到目前为止,一切都很好。这提供了一组不错的MatchInfo对象:

IgnoreCase                    LineNumber Line                          Filename                      Pattern                       Matches
----------                    ---------- ----                          --------                      -------                       -------
    True                            30   ...                           file.jsp                      ...                           {...}

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

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

哪个给出:

Groups        Success Captures                 Index     Length Value
------        ------- --------                 -----     ------ -----
{...}         True    {...}                    49        47     ...

或作为带有| Format-List:的列表

Groups   : {matched text, captured group}
Success  : True
Captures : {matched text}
Index    : 39
Length   : 33
Value    : matched text

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

我尝试添加另一个| ForEach-Object -MemberName Groups,但它似乎返回了与上面相同的结果。

我得到的最接近的是| Select-Object -Property Groups,它确实给了我所期望的(集合列表):

Groups
------
{matched text, captured group}
{matched text, captured group}
...

但后来我无法从每个集合中提取捕获的组,我尝试使用| Select-Object -Index 1,我只得到其中一个集合。


更新:可能的解决方案

似乎通过添加| ForEach-Object { $_.Groups.Groups[1].Value },我得到了我想要的东西,但我不明白为什么——所以当将这种方法扩展到整组文件时,我不能确定我是否能够得到正确的结果。

为什么它有效?

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

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

看看下面的

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

$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/

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

"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

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

使用-match运算符时,powershell将创建一个名为$Matches自动变量

PS> "The last logged on user was CONTOSOjsmith" -match "(.+was )(.+)"

此表达式返回的值仅为true|false,但PS将添加$Matches哈希表

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

PS> $Matches
Name     Value
----     -----
2        CONTOSOjsmith
1        The last logged on user was
0        The last logged on user was CONTOSOjsmith

你可以用这样的点符号单独访问每个捕获组:

PS> "The last logged on user was CONTOSOjsmith" -match "(.+was )(.+)"
PS> $Matches.2
CONTOSOjsmith

其他资源

  • 要获取多个匹配项,请参阅如何捕获多个正则表达式匹配项
  • 要传递选项/标志,请参阅将regex选项传递给PowerShell [regex]类型

这适用于我的情况。

使用文件:test.txt

// autogenerated by script
char VERSION[21] = "ABCDEFGHIJKLMNOPQRST";
char NUMBER[16] = "123456789012345";

从文件中获取NUMBER和VERSION。

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

答案较晚,但为了循环多个匹配和组,我使用:

$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
}

此脚本将从文件的内容中获取regex指定的捕获组,并将其匹配项输出到控制台。


$file是您要加载的文件
$cg是您想要获取的捕获组
$regex是正则表达式模式



要加载的示例文件及其内容:

C: \some\file.txt

This is the especially special text in the file.



示例使用:.get_regex_capture.ps1 -file "C:somefile.txt" -cg 1 -regex 'b(specialWw+)'

输出:special text


get_regex_capture.ps1

Param(
    $file=$file,
    [int]$cg=[int]$cg,
    $regex=$regex
)
[int]$capture_group = $cg
$file_content = [string]::Join("`r`n", (Get-Content -Raw "$file"));
Select-String -InputObject $file_content -Pattern $regex -AllMatches | % { $_.Matches.Captures } | % { echo $_.Groups[$capture_group].Value }

相关内容

  • 没有找到相关文章

最新更新