在ForEach-Object中使用Where-Object和Matches中的匹配是否有效

时间:2017-03-10 23:37:40

标签: powershell foreach where race-condition powershell-v5.0

简短问题

使用以下方法是否有效/安全:

$SomeArray | ?{$_ -match $Pattern} | %{$Matches.CapturingGroupName}

而不是:

$SomeArray | %{if($_ -match $Pattern){$Matches.CapturingGroupName}}

您为什么要这样做?

  • 第一种方法看起来更优雅。
  • 可能会有一些性能提升;例如如果where-objectforeach-object脚本块中有额外的代码,这些代码已知耗时(例如IO或网络操作)。

更多信息

我编写了大量使用-matchwhere-object)过滤器中?{<#...#>}语句的代码,然后在{{1}中引用$matchesforeach-object)语句。

在我第一次这样做之前,我测试了很多,以确保%{<#...#>}变量始终为前一个匹配的结果;即确保在继续使用下一个元素之前使用管道不允许该变量更新。我甚至包括代码以确保它不受竞争条件的影响。

测试代码

$matches
  • 第1行和第2行只是为了调整你必须等待测试完成/测试的彻底程度。
  • 第3行是要测试的代码:
    • 从1到2000计算
    • 将每个数字转换为字符串
    • 使用$TestMax = 1000 #test 1000 times $SleepMS = 1000 #wait 1 second between each test to allow the feeding match a headstart on the matches $Evens = 1..(2*$TestMax) | %{"$_"} | ?{$_ -match '^(?<EvenNumber>.*[02468])$'} | %{Start-Sleep -Milliseconds $SleepMS; $matches.EvenNumber} if ((Compare-Object $Evens (1..$TestMax | %{"$($_*2)"}) ) -eq $null) {":)"} else {":("} 来测试数字是否均匀(注意:此代码仅用于演示问题;我从未使用此方法来测试实际中的均匀度)
    • 等一下;这是-match循环的开始,试图创建一个竞争条件,where-object可以超越where-object;因此在读取之前更改foreach-object值。
    • 返回使其成为结果的每个数字。
  • 第4行将我们的结果与预期结果进行比较(即我们测试范围内的偶数,以字符串形式保存);如果它通过就会露出笑脸。

这可以按预期工作(即我们得到一个笑脸)。

为什么要关注?

我做了一些愚蠢的事......我在$matchessort-object之间添加了一个where(出于正当理由),在一个脚本阻止管道输入时是否存在竞争条件下一个(即使包括人为延迟)在添加其他块时也不会出现问题。我忘了的是foreach必须先看到所有内容才能输出第一个结果;因此sort将永远是最后一场比赛。

即。第3行现在是:

$matches

虽然这在使用$Evens = 1..(2*$TestMax) | %{"$_"} | ?{$_ -match '^(?<EvenNumber>.*[02468])$'} | sort | %{Start-Sleep -Milliseconds $SleepMS; $matches.EvenNumber} 时完全有意义,但这也意味着不能保证一个脚本块会跟随另一个脚本块;尽管它在我原来的测试中做到了。因此,只要我在sortwhere之间不包含任何内容,这种行为(即我在原始问题中描述的内容)将始终如我所期望的那样是安全的。块;或者这只是一个等待咬我的假设?

更易读的测试代码版本

foreach

0 个答案:

没有答案