在 Powershell 中捕获正则表达式

Capturing Regex in Powershell

我正在解决这个问题。我想获取文本中所有匹配我的模式的 URL。应该包括 URL 的第一个参数,但不包括第二个参数。

两期:

  1. 它没有得到第一个 URL
  2. 我不知道捕获是如何工作的。

在方法 1 中,我看到了匹配项,但没有看到括号中的捕获文本。在方法 2 中,我在一些输出上看到了我的捕获,但得到了包含比我的捕获更多的额外输出。我喜欢方法 2 风格,但使用方法 1 是为了试图理解发生了什么,但只是给自己挖了一个更深的洞。

$fileContents = 'Misc Text < a href="http://example.com/Test.aspx?u=a1">blah blah</a>  More Stuff <a href="http://example.com/Test.aspx?u=b2&parm=123">blah blah </a> Closing Text'


#Sample URL           http://example.com/Test.aspx?u=a1&parm=123 
$pattern = '<a href="(http://example.com/Test.aspx\?u=.*?)[&"]'
Write-Host "RegEx Pattern=$pattern"

Write-Host "----------- Method 1 --------------"  
$groups = [regex]::Matches($fileContents, $pattern)
$groupnum = 0 
foreach ($group in $groups)  
{
    Write-Host "Group=$groupnum URL=$group " 
    $capturenum = 0 
    foreach ($capture in $group.Captures) 
    {
        Write-Host "Group=$groupnum Capture=$capturenum URL=$capture.value index=$($capture.index)" 
        $capturenum = $capturenum + 1 
    }
    $groupnum = $groupnum + 1 
}

Write-Host "----------- Method 2 --------------"  
$urls = [regex]::Matches($fileContents, $pattern).Groups.Captures.Value 
#$urls = $urls | select -Unique

Write-Host "Number of Matches = $($urls.Count)"


foreach ($url in $urls) 
    {
    Write-Host "URL: $url "
    }

Write-Host " " 

输出:

----------- Method 1 --------------
Group=0 URL=<a href="http://example.com/Test.aspx?u=b2& 
Group=0 Capture=0 URL=<a href="http://example.com/Test.aspx?u=b2&.value index=81
----------- Method 2 --------------
Number of Matches = 2
URL: <a href="http://example.com/Test.aspx?u=b2& 
URL: http://example.com/Test.aspx?u=b2 

Powershell 版本 5.1.17763.592

I'm missing how the capture works.

捕获组 0 始终 整个匹配 - 未命名的捕获组将编号为 1 到 9,因此您需要组 1。

我重命名了这些变量以使其含义更清楚:

$MatchList = [regex]::Matches($fileContents, $pattern)

foreach($Match in $MatchList){
  for($i = 0; $i -lt $Match.Groups.Count; $i++){
    "Group $i is: $($Match.Groups[$i].Value)"
  }
}

如果您想收集所有捕获的 url,只需执行以下操作:

$urls = foreach($Match in $MatchList){
  $Match.Groups[$i].Value
}

如果您只需要第一个匹配项,则无需手动调用 [regex]::Matches() - PowerShell 会在您使用时自动将任何捕获组的字符串值注入自动 $Matches 变量-match 运算符,所以如果你这样做:

if($fileContents -match $pattern){
    "Group 1 is $($Matches[1])"
}
# or
if($fileContents -match $pattern){
    $url = $Matches[1]
}

...您将得到预期的结果:

Group 1 is http://example.com/Test.aspx?u=b2

使用带有参数 -AllMatchesSelect-String 来获取输入字符串中的所有匹配项。您的正则表达式应如下所示:(?<=a href=")[^"]*。这将匹配字符串 a href=" 之后的任何不是双引号的字符(最后一个字符串不包含在匹配中)。现在你只需要扩展匹配的值就大功告成了。

$re = '(?<=a href=")[^"]*'
$fileContents |
    Select-String -Pattern $re -AllMatches |
    Select-Object -Expand Matches |
    Select-Object -Expand Value