Mac*_*ack 3 powershell list object
这是另一个问题的衍生物,它位于此处: 将对象格式化为一个整齐的列表 我认为,参数的基础是错误的,因为我们之后不处理对象的格式化.这仅适用于控制台显示的外观,但在操作包含对象的变量时,它可能会影响对象的完整性.
我需要的是创建一个固有输出列表(而不是表)的对象.我知道这是可能的,因为我已经测试了许多我没有写过的函数,而且创建的对象实际上是列表.无需使用Format-List来扭曲或塑造已存在的内容.我只是无法弄清楚为什么有时输出是列表或表.我不确定魔法在哪里.但是我确实知道,当我$Host在运行包含创建对象的变量之前运行时,我得到了Host生成的对象,这是一个列表,然后将对象的形状也作为通常显示为表的列表.当然,这可能会给出我想要的结果,但我不打算显示主机信息.那么解决方案是什么呢,我希望有人可以解释一下.
PowerShell在向用户显示数据/对象时执行一些默认格式设置.通常,对象在具有最多4个属性时以表格形式显示,而在具有4个以上属性时以列表形式显示.
如果连续输出多个内容,PowerShell会将第一个对象的格式(列表/表)应用于所有后续对象.我不知道这种行为背后的确切原因,但可能是为了使输出更加一致.
示范:
PS C:\> $o1 = New-Object -Type PSObject -Property @{a=1;b=2;c=3;d=4;e=5}
PS C:\> $o2 = New-Object -Type PSObject -Property @{x='foo';y='bar'}
PS C:\> $o1
c : 3
e : 5
d : 4
b : 2
a : 1
PS C:\> $o2
y x
- -
bar foo
PS C:\> $o1; $o2
c : 3
e : 5
d : 4
b : 2
a : 1
y : bar
x : foo
但是,请注意,如果以错误的顺序输出对象,依赖此行为可能会导致意外结果:
PS C:\> $o2; $o1
y x
- -
bar foo # ← properties of $o2
# ← empty line for $o1!
$o1显示为在上述输出一个空行,因为输出$o2首先建立表格输出格式与列y和x,但$o1不具有这些特性.缺少的属性在表格输出中显示为空值,而输出中省略了其他属性.在某些情况下,您可能会以列表形式从第二个对象/列表中获取输出(例如Get-Process; Get-ChildItem,在PowerShell控制台中运行).
您可以通过管道Format-Table(或Format-List)cmdlet 将后续对象或对象数组强制显示为单独的表(或列表):
PS C:\> $o2; $o1 | Format-Table
y x
- -
bar foo
c e d b a
- - - - -
3 5 4 2 1
您还可以强制PowerShell通过管道传递(例如)来单独显示每个变量Out-Default:
PS C:\> $o2 | Out-Default; $o1 | Out-Default y x - - bar foo c : 3 e : 5 d : 4 b : 2 a : 1
但请注意,这会写入控制台,因此无法再捕获,重定向或流水线化生成的输出.仅在您想要向用户显示内容时使用此选项.
有关PowerShell输出格式的其他信息,请参阅此处.
有一些方法可以改变对象显示方式的默认行为,但遗憾的是它们并不简单.首先,您可以定义默认显示属性集,以使PowerShell不显示所有属性,而只显示特定子集.
PS C:\> $props = 'c', 'd'
PS C:\> $default = New-Object Management.Automation.PSPropertySet('DefaultDisplayPropertySet',[string[]]$props)
PS C:\> $members = [Management.Automation.PSMemberInfo[]]@($default)
PS C:\> $o1 | Add-Member MemberSet PSStandardMembers $members
PS C:\> $o1
c d
- -
3 4
您仍然可以使用Format-List *以下方式显示所有属性:
PS C:\> $o1 | Format-List * c : 3 e : 5 d : 4 b : 2 a : 1
定义默认显示属性集不允许您定义输出格式.为此,您可能需要编写自定义格式文件.为此,您可能还需要为对象定义自定义类型.
$formatFile = "$HOME\Documents\WindowsPowerShell\Your.Format.ps1xml"
$typeFile = "$HOME\Documents\WindowsPowerShell\Your.Type.ps1xml"
@'
<?xml version="1.0" encoding="utf-8" ?>
<Configuration>
<ViewDefinitions>
<View>
<Name>Default</Name>
<ViewSelectedBy>
<TypeName>Foo.Bar</TypeName>
</ViewSelectedBy>
<ListControl>
...
</ListControl>
</View>
</ViewDefinitions>
</Configuration>
'@ | Set-Content $formatFile
Update-FormatData -AppendPath $formatFile
@'
<?xml version="1.0" encoding="utf-8" ?>
<Types>
<Type>
<Name>Foo.Bar</Name>
<Members>
...
</Members>
</Type>
</Types>
'@ | Set-Content $typeFile
Update-TypeData -AppendPath $typeFile
$o2.PSTypeNames.Insert(0, 'Foo.Bar')
Run Code Online (Sandbox Code Playgroud)
杰弗里希克斯写了一篇 关于这个主题的系列 文章,你可能想要阅读.
尽管如此,除非你有非常令人信服的理由,否则我不建议走这条路.我之前尝试解释过,但是@TesselatingHeckler比我更简洁,所以我要引用他的话:
PowerShell不是bash,它具有内容和表示的分离,就像HTML和CSS一样.
您通常要在PowerShell中执行的操作是将数据保存在对象中,并使这些对象的属性包含"原始"(即未格式化)数据.这为您提供了处理数据的最大灵活性.格式化数据通常只会妨碍您,因为它会强制您再次解析/转换数据.仅在需要将数据显示给用户时格式化数据,并使用Format-*cmdlet执行此操作.如果您的输出是用于进一步处理:首先不要打扰它的格式.将它留给用户如何显示数据.