通过 RegEx 在 Powershell 中匹配和 $Matches

Match and $Matches in Powershell via RegEx

我的 Powershell 项目有点问题,我已经研究了一段时间了。

基本思路是执行六次 iPerf 速度测量。 创建一个日志文件以包含一些可以显示给用户的数据。

但是 Powershell 中的 match 和变量 Matches 显示多个值存在一些问题..

有代码,我一直在努力..


     = (Get-Content -Path 'iperf3.txt' -TotalCount 398)[-1] # Fetch details about speed measurements for download
     = (Get-Content -Path 'iperf3.txt' -TotalCount 796)[-1] # Fetch details about speed measurements for upload
     = (Get-Content -Path 'iperf3.txt' -TotalCount 1195)[-1] # Same as above
     = (Get-Content -Path 'iperf3.txt' -TotalCount 1593)[-1] # Same as above
     = (Get-Content -Path 'iperf3.txt' -TotalCount 1992)[-1] # Same as above
     = (Get-Content -Path 'iperf3.txt' -TotalCount 2390)[-1] # Same as above

通过 Get-Content 和 TotalCount 输出


    [SUM]   0.00-30.00  sec  1.09 GBytes   313 Mbits/sec                  receiver
    [SUM]   0.00-30.00  sec  1.09 GBytes   312 Mbits/sec                  receiver
    [SUM]   0.00-30.00  sec  1.11 GBytes   317 Mbits/sec                  receiver
    [SUM]   0.00-30.00  sec  1.09 GBytes   311 Mbits/sec                  receiver
    [SUM]   0.00-30.00  sec  1.11 GBytes   317 Mbits/sec                  receiver
    [SUM]   0.00-30.00  sec  1.09 GBytes   312 Mbits/sec                  receiver

之后,我使用正则表达式和变量输出 Mbits/sec 之前的数字,并从这行代码中包含 Mbits/sec..


     -match '\d+\sMbits[/]sec'
     -match '\d+\sMbits[/]sec'

etc.

我做变量匹配来验证变量是 True,并收到 312Mbits/sec 的输出,但仅此而已。

现在这是我看不到代码错误的地方。变量通过了,它是真的,但我只有一个 Value as 313 Mbits/sec via Value.

我想我会在 [=51] 中同时看到 313 Mbits/sec312 Mbits/sec =]提示。

我是不是在使用 match/Matches variable/function 时做错了什么?

任何反馈and/or建议将不胜感激。

automatic $Matches variable only ever reflects the results of the most recent -match 操作 - 然后仅当 (a) 匹配 成功 和 (b) 从根本上说,仅当 LHS 是 single string - 如果 LHS 是一个 collection(数组),-match 充当 filter,返回 匹配元素的子数组 ,并且 填充 $Matches.

但是,您的命令可以大大简化:

  • 使用Get-Content调用
  • 使用带有 -Index 参数的 Select-Object 调用来提取感兴趣的行(索引基于 0)。
  • 使用 -replace 运算符而不是 -match 以直接提取感兴趣的子字符串:
(
  Get-Content 'iperf3.txt' | Select-Object -Index 397,795,1194,1592,1991,2389
) -replace '.+\b(\d+\sMbits/sec).+', '' 

退一步:

而不是select通过固定索引(行号)select感兴趣的行正则表达式[=] 49=] 也允许您使用单个 Select-String 调用:

Select-String -LiteralPath 'iperf3.txt' -Pattern '\s*\[SUM].+\b(\d+\sMbits/sec).+' |
  ForEach-Object {
    $_.Matches.Groups[1].Value
  }

您没有做错任何事,这只是 -match 运算符的默认行为以及 $Matches automatic variable 的填充方式。

这是 Matching operators 的摘录,很好地解释了它的工作原理:

It is important to note that the $Matches hashtable contains only the first occurrence of any matching pattern.

您有 2 个解决方法,第一个可以使用 Regex.Matches Method 查找匹配模式的所有外观:

$string = @'
[SUM]   0.00-30.00  sec  1.09 GBytes   313 Mbits/sec                  receiver
[SUM]   0.00-30.00  sec  1.09 GBytes   312 Mbits/sec                  receiver
[SUM]   0.00-30.00  sec  1.11 GBytes   317 Mbits/sec                  receiver
[SUM]   0.00-30.00  sec  1.09 GBytes   311 Mbits/sec                  receiver
[SUM]   0.00-30.00  sec  1.11 GBytes   317 Mbits/sec                  receiver
[SUM]   0.00-30.00  sec  1.09 GBytes   312 Mbits/sec                  receiver
'@

[regex]::Matches($string, '\d+\sMbits[/]sec').Value

请注意,在上面的示例中,$string 是一个 multi-line 字符串 ,但在示例中 将是一个数组 因为它需要一个循环。

$string = @'
[SUM]   0.00-30.00  sec  1.09 GBytes   313 Mbits/sec                  receiver
[SUM]   0.00-30.00  sec  1.09 GBytes   312 Mbits/sec                  receiver
[SUM]   0.00-30.00  sec  1.11 GBytes   317 Mbits/sec                  receiver
[SUM]   0.00-30.00  sec  1.09 GBytes   311 Mbits/sec                  receiver
[SUM]   0.00-30.00  sec  1.11 GBytes   317 Mbits/sec                  receiver
[SUM]   0.00-30.00  sec  1.09 GBytes   312 Mbits/sec                  receiver
'@ -split '\r?\n'

foreach($line in $string) {
    if($line -match '\d+\sMbits[/]sec') {
        $Matches[0]
    }
}

GitHub issue #7867 建议向 PowerShell 添加一个 -matchall 运算符,如果您认为这会有所帮助,请考虑 up-voting。