Powershell Select-Object 与 ForEach 在 Select-String 结果上的比较
假设我在变量 $mat 中调用 Select-String 的结果,从文件内容解析正则表达式:
$mat = cat errors.txt | Select-String "'(?<code>\w+)'.+ID (?<id>[^:]+)"
根据 $mat | 的输出Get-Member
结果包含 Match[]
类型的 Matches 属性。
当我执行以下命令时,我得到了正则表达式输出的所有匹配项:
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
Let's say I have the results of a call to Select-String in a variable $mat, parsing a regular expression from file contents:
$mat = cat errors.txt | Select-String "'(?<code>\w+)'.+ID (?<id>[^:]+)"
According to the output of $mat | Get-Member
the result contains a Matches property of type Match[]
.
When I execute the following I get all the matches of my regular expression output:
PS > $mat | Select-Object -Property Matches
Matches
-------
{'ACCFWD', ID 16}
{'EQASIAN', ID 448}
Why doesn't this next block of code using foreach to select the Matches have the same output:
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
显示属性时,PowerShell 会将
*.format.ps1xml
文件中未定义显示格式的类型的属性自动格式化为最多包含 4 个属性的表格。 5 个或更多属性显示为列表。当您使用Select-Object
选择 Matches 属性时,您正在选择Microsoft.PowerShell.Commands.MatchInfo
对象的单个属性。使用Foreach-Object
,您可以显示System.Text.RegularExpressions.Match
对象的所有属性。使用
Select-Object -ExpandProperty Matches
将使输出看起来与Foreach
相同,因为它将输出RegularExpressions.Match
对象。如果将
Get-Member
放置在两个生成输出的示例之后,您将看到它们输出不同类型的对象。编辑:以下是对每个命令发生的格式的说明。
Select-String
的输出是一个Microsoft.PowerShell.Commands.MatchInfo
对象,它有 8 个属性。默认情况下不会显示这些属性,因为MatchInfo
的显示格式是在PowerShellCore.format.ps1xml
中定义的,用于显示MatchInfo
的结果ToString()
方法。在本例中,
Select-Object
的输出是一个自定义Selected.Microsoft.PowerShell.Commands.MatchInfo
对象,其Matches
属性为从MatchInfo
对象复制。由于没有为Selected.Microsoft.PowerShell.Commands.MatchInfo
类型定义默认显示格式,PowerShell 会自动将其格式化为表格,因为它的属性少于 5 个(在本例中Matches
是唯一的属性)。在
Foreach-Object
ScriptBlock 中,正在输出MatchInfo
对象的Matches
属性。Matches
属性是一个System.Text.RegularExpressions.Match
,它有 6 个属性。由于没有为System.Text.RegularExpressions.Match
类型定义默认显示格式,因此Match
对象将显示为列表,因为属性超过 4 个。When displaying properties, PowerShell auto-formats the properties of types that do not have a display format defined in a
*.format.ps1xml
file as a table for up to 4 properties. 5 or more properties displays as a list. When you select the Matches property withSelect-Object
, you are selecting a single property of theMicrosoft.PowerShell.Commands.MatchInfo
object. WithForeach-Object
you are displaying all of the properties for aSystem.Text.RegularExpressions.Match
object.Using
Select-Object -ExpandProperty Matches
will cause the output to look the same as theForeach
because it will outputRegularExpressions.Match
objects.If you place
Get-Member
after both of your examples that produce output you will see that they output different types of objects.Edit: Here is an explanation of the formatting that happens for each command.
The output of
Select-String
is aMicrosoft.PowerShell.Commands.MatchInfo
object which has 8 properties. These properties are not displayed by default because the display format forMatchInfo
is defined inPowerShellCore.format.ps1xml
to show the result ofMatchInfo
'sToString()
method.In this case, the output of
Select-Object
is a customSelected.Microsoft.PowerShell.Commands.MatchInfo
object with theMatches
property that was copied from theMatchInfo
object. Since there is no default display format defined for theSelected.Microsoft.PowerShell.Commands.MatchInfo
type, PowerShell auto formats it as a table since it has less than 5 properties (In this caseMatches
is the only property).In the
Foreach-Object
ScriptBlock, theMatches
property of theMatchInfo
object is being output. TheMatches
property is aSystem.Text.RegularExpressions.Match
which has 6 properties. Since there is no default display format defined for theSystem.Text.RegularExpressions.Match
type, theMatch
objects are displayed as a list because there are more than 4 properties.如果您使用 -ExpandProperty 而不是 -Property,则两个输出将相同。
这适用于这个特定的示例,但对于访问单个属性,Select-Object -ExpandProperty 在所有情况下仍然与 ForEach 不完全相同。我会使用 ForEach。另请参阅此示例: http://community.idera.com/powershell/powertips/b/tips/posts/use-foreach-object-instead-of-select-object-expandproperty
If you use -ExpandProperty instead of -Property, then the two outputs will be the same.
That works for this particular example, but for accessing a single property, Select-Object -ExpandProperty is still not exactly the same as ForEach in all cases. I would use ForEach. Also, see this example: http://community.idera.com/powershell/powertips/b/tips/posts/use-foreach-object-instead-of-select-object-expandproperty