如何创建输出列表(不是表)的对象 [英] How to create an Object that outputs a List (Not A Table)

查看:66
本文介绍了如何创建输出列表(不是表)的对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是另一个问题的衍生结果,该问题位于此处: 将对象格式化为外观整齐的列表 我认为,该论据的基础是错误的,因为此后我们将不再处理对象的格式化.这仅用于控制台显示的外观,但是在您操纵包含对象的变量时,它可能与对象的完整性有关.

This is a spin-off from another question which is located here: Formatting an Object as a neatly looking list The basis of the argument, I believe, was wrong since we're not dealing with formatting of the object afterwards. That's only for looks as shown by the console but it can have bearing on the integrity of the object as you manipulate the variable containing the object.

我需要创建一个对象,该对象固有地输出一个列表(而不是一个表).我知道这是可能的,因为我已经测试了许多我尚未编写的功能,并且创建的对象实际上是列表.无需使用Format-List来扭曲或塑形已经存在的内容.我只是无法弄清楚为什么有时输出是列表或表.我不确定魔术在哪里.但是我确实知道,当我运行$Host之前,在运行包含已创建对象的变量之前,我得到了Host生成的对象,该对象是一个列表,然后将该对象成形为一个列表,该列表通常会以表格形式显示.当然,这可能会提供所需的结果,但我不想显示主机信息.那么解决方案是什么,我希望有人能解释一下.

What I need is to create an object that inherently outputs a list (not a table). I know it's possible because I've tested many functions that I've not written and the objects created are in fact lists. No need to use Format-List to distort or shape what's already there. I just have not being able to figure out why sometimes the output is a list or a table. I'm not sure where the magic is. However I do know that when I run $Host before I run the variable containing the created object I get the object that Host produces, which a list, and that shapes the object afterwards also as a list that normally would be shown as a table. Of course, that may give the result I want but I'm not looking to show the Host information. So what is the solution to this, I wish someone could explain this.

推荐答案

PowerShell在向用户提供数据/对象时会执行一些默认格式.通常,当对象具有最多4个属性时,它们以表格形式显示;而当对象具有4个以上属性时,则以列表形式显示.

PowerShell does some default formatting when it presents data/objects to the user. Usually objects are displayed in tabular form when they have up to 4 properties, and in list form when they have more than 4 properties.

如果连续输出多个内容,PowerShell会将第一个对象的格式(列表/表)应用于所有后续对象.我不知道此行为的确切原因,但大概是为了使输出更一致.

If you output several things in a row, PowerShell applies the format (list/table) from the first object to all subsequent objects. I don't know the exact reasoning behind this behavior, but presumably it's to make the output more consistent.

演示:


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

但是请注意,如果您以错误的顺序输出对象,则依赖于此行为可能会导致不良结果:

Beware, however, that relying on this behavior might lead to undesired results if you output objects in the wrong order:


PS C:\> $o2; $o1

y                                    x
-                                    -
bar                                  foo         # ← properties of $o2
                                                 # ← empty line for $o1!

$o1在上述输出中显示为空白行,因为输出$o2首先会建立具有列yx的表格输出格式,但是$o1没有这些属性.缺少的属性在表格输出中显示为空白值,而其他属性从输出中省略.在某些情况下,您可能会从列表形式的第二个对象/列表中获取输出(在PowerShell控制台中以实例Get-Process; Get-ChildItem运行).

$o1 appears as a blank line in the above output, because outputting $o2 first establishes tabular output format with the columns y and x, but $o1 doesn't have these properties. Missing properties are displayed as blank values in tabular output, whereas additional properties are omitted from the output. There are also cases where you might get the output from the second object/list in list form (run for instance Get-Process; Get-ChildItem in a PowerShell console).

通过将它们通过Format-Table(或Format-List)cmdlet管道输送,可以强制将随后的对象或对象数组显示为单独的表(或列表):

You can force subsequent objects or object arrays to be displayed as separate tables (or lists) by piping them through the Format-Table (or 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:

You can also force PowerShell to display each variable individually by piping them through (for instance) Out-Default:


PS C:\> $o2 | Out-Default; $o1 | Out-Default

y   x
-   -
bar foo

c : 3
e : 5
d : 4
b : 2
a : 1

但是,请注意,这将写入控制台,因此无法再捕获,重定向或通过管道传输结果输出.仅当您想向用户显示某些内容时,才使用此功能.

Note, however, that this writes to the console, so the resulting output can't be captured, redirected, or pipelined anymore. Use this only if you want to display something to a user.

有关PowerShell输出格式的其他信息请参阅此处.

For additional information about PowerShell output formatting see here.

有多种方法可以更改对象显示方式的默认行为,但不幸的是,它们并不十分简单.一方面,您可以定义

There are ways to change the default behavior of how an object is displayed, but unfortunately they're not exactly straightforward. For one thing you can define a default display property set to have PowerShell display not all properties, but just a particular subset.


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 *来显示所有属性:

You can still get all properties displayed by using Format-List *:


PS C:\> $o1 | Format-List *

c : 3
e : 5
d : 4
b : 2
a : 1

尽管定义默认的显示属性集,但您无法定义输出格式.为此,您可能需要编写自定义格式化文件.为此,您可能还需要定义一个自定义类型用于您的对象.

Defining the default display property set doesn't allow you to define the output format though. To do that you probably need to write a custom formatting file. For that to work you probably also need to define a custom type for your objects.

$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')

Jeffrey Hicks写了文章 系列

Jeffrey Hicks wrote an article series on the subject that you may want to read.

话虽如此,除非您有非常令人信服的理由,否则我不建议您选择这条路线.我曾尝试对其进行解释,但

With all of that said, I would not recommend going this route unless you have very compelling reasons to do so. I tried to explain it before, but @TesselatingHeckler put it much more concisely than me, so I'm going to quote him on this:

PowerShell不是bash,它具有内容和表示形式的分离,就像HTML和CSS一样.

PowerShell is not bash, it has a separation of content and presentation, like HTML and CSS have.

您通常需要在PowerShell中执行的操作是将数据保留在对象中,并使这些对象的属性包含原始"(即,未格式化的)数据.这为您提供了最大的灵活性来处理数据.格式化的数据通常只会妨碍您的操作,因为它会迫使您再次解析/转换数据.仅在需要向用户显示数据时格式化数据,然后使用Format-* cmdlet进行格式化.而且,如果您的输出打算用于进一步处理:不要一开始就对它进行格式化.留给用户他想如何显示数据.

What you normally want to do in PowerShell is keep your data in objects, and have the properties of these objects contain the "raw" (i.e. unformatted) data. That gives you the most flexibility for processing your data. Formatted data usually only gets in the way, because it forces you to parse/convert the data again. Format your data only when you need to display it to a user, and use the Format-* cmdlets to do so. And if your output is intended for further processing: don't bother formatting it in the first place. Leave it to the user how he wants to display the data.

这篇关于如何创建输出列表(不是表)的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆