通过 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/sec 和 312 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。
我的 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/sec 和 312 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。