选择字符串结果的Powershell Select-Object vs ForEach

时间:2011-09-09 14:00:04

标签: regex powershell

假设我在变量$ mat中调用Select-String的结果,从文件内容中解析正则表达式:

$mat = cat errors.txt | Select-String "'(?<code>\w+)'.+ID (?<id>[^:]+)" 

根据$mat | Get-Member的输出,结果包含类型Match[]的匹配属性。

当我执行以下操作时,我得到正则表达式输出的所有匹配项:

PS > $mat | Select-Object -Property Matches

Matches                                                                                                                                                                              
-------                                                                                                                                                                              
{'ACCFWD', ID 16}                                                                                                                                                                    
{'EQASIAN', ID 448}                   

为什么下一个使用foreach选择匹配的代码块没有相同的输出:

    PS > $mat | ForEach { $_.Matches } 


Groups   : {'ACCFWD', ID 16, ACCFWD, 16}
Success  : True
Captures : {'ACCFWD', ID 16}
Index    : 20
Length   : 15
Value    : 'ACCFWD', ID 16

Groups   : {'EQASIAN', ID 448, EQASIAN, 448}
Success  : True
Captures : {'EQASIAN', ID 448}
Index    : 20
Length   : 17
Value    : 'EQASIAN', ID 448

谢谢!

2 个答案:

答案 0 :(得分:9)

显示属性时,PowerShell会自动格式化不具有*.format.ps1xml文件中定义的显示格式的类型的属性,作为最多4个属性的表。 5个或更多属性显示为列表。当您使用Select-Object选择“匹配”属性时,您将选择Microsoft.PowerShell.Commands.MatchInfo对象的单个属性。使用Foreach-Object,您将显示System.Text.RegularExpressions.Match对象的所有属性。

使用Select-Object -ExpandProperty Matches会使输出看起来与Foreach相同,因为它会输出RegularExpressions.Match个对象。

如果在产生输出的两个示例之后放置Get-Member,您将看到它们输出不同类型的对象。

编辑:以下是对每个命令进行格式化的说明。

cat errors.txt | Select-String "'(?<code>\w+)'.+ID (?<id>[^:]+)"

Select-String的输出是一个Microsoft.PowerShell.Commands.MatchInfo对象,它有8个属性。默认情况下不会显示这些属性,因为MatchInfo的显示格式在PowerShellCore.format.ps1xml中定义,以显示MatchInfo的{​​{1}}方法的结果。

ToString()

在这种情况下,$mat | Select-Object -Property Matches 的输出是自定义Select-Object对象,其Selected.Microsoft.PowerShell.Commands.MatchInfo属性是从Matches对象复制的。由于没有为MatchInfo类型定义默认显示格式,因此PowerShell会将其格式化为表格,因为它具有少于5个属性(在这种情况下,Selected.Microsoft.PowerShell.Commands.MatchInfo是唯一的属性)。

Matches

$mat | ForEach { $_.Matches } ScriptBlock中,正在输出Foreach-Object对象的Matches属性。 MatchInfo属性是Matches,有6个属性。由于没有为System.Text.RegularExpressions.Match类型定义默认显示格式,System.Text.RegularExpressions.Match对象显示为列表,因为有超过4个属性。

答案 1 :(得分:1)

如果使用-ExpandProperty而不是-Property,那么两个输出将是相同的。

$mat | Select-Object -ExpandProperty Matches

这适用于此特定示例,但是对于访问单个属性,Select-Object -ExpandProperty在所有情况下仍然与ForEach不完全相同。我会用ForEach。另请参阅此示例:http://community.idera.com/powershell/powertips/b/tips/posts/use-foreach-object-instead-of-select-object-expandproperty