PowerShell 4.0 多段Select-Object取不同属性时仅返回首条执行结果问题咨询
根本原因
这个问题和XML文件、是否重新加载文档完全无关,是PowerShell 4.0两个固有行为叠加触发的:
- 当你给
Select-Object -Property传裸的脚本块(比如{$_.id}、{$_.name},没有用哈希表定义明确的属性名),Select-Object不会自动为计算出来的值设置友好的属性名,而是直接把这个脚本块的完整字符串内容,当成生成的自定义对象的属性名。
举个例子:写Select-Object -Property {$_.id},输出的对象不会有一个叫id的属性,它的属性名就是整串字符串"$_.id";写{$_.name}时,输出对象的属性名就是"$_.name"。 - PowerShell控制台的默认格式化引擎,处理同一输出流里连续传入的对象时,会以第一个送达格式化环节的对象的属性集为基准,一次性确定整个表格的列结构。一旦列结构定了,后面传进来的对象如果不匹配已有列的属性,对应的属性值会被直接丢弃,引擎不会主动为新出现的属性新增表格列。
和你观察到的现象完全对应的逻辑
- 当你两条Select语句用的脚本块完全一样,两个输出对象的属性名是完全相同的(比如都是
"$_.name")。第一个对象过来时,格式化引擎建好对应列头的表格,第二个对象因为属性名完全匹配,能正常在这一列输出值,所以你能看到“SmallTime”“TinyTime”两行结果。 - 当你两条Select语句的脚本块不一样时,第一条Select输出的对象会让格式化引擎建一个列头是
"$_.id"的单列表格;第二条Select输出的对象,属性名是"$_.name",根本没有第一个对象定义的"$_.id"这个属性,它的值匹配不上已有列,最终会被格式化引擎直接丢弃,你就只能看到第一条语句输出的“456”,第二条的结果完全不显示。 - 你之前尝试重新加载XML的操作没用,是因为这个问题根本和XML的加载状态没关系——哪怕你把文件读十遍,只要两个输出的对象属性名对不上,格式化引擎还是会按第一个的结构建表,忽略第二个的内容。
可落地的解决方向
- 别给
Select-Object传裸脚本块,用带明确命名的哈希表格式定义计算属性,比如:
这样生成的对象属性名就是明确的Select-Object -Property @{ Name = 'GroupID'; Expression = {$_.id} }GroupID,不会出现属性名是脚本块字符串的情况。 - 对于查询返回结构不一样的内容,在每段输出后面手动加独立的格式化指令(比如
Format-Table -AutoSize),让每段查询生成独立的表格,不会共用全局的列结构。 - 如果不需要输出结构化对象,直接取值输出原始文本就行,不用套
Select-Object,比如直接写:
这样输出的是纯字符串值,不会触发表格格式化的逻辑,也就不会有列不匹配丢输出的问题。($xmlDocument.flowController.rootGroup.processGroup | Where-Object {$_.name -eq 'SmallTime'}).id
内容的提问来源于stack exchange,提问作者mikec
相关产品推荐
相关产品推荐

