使用 Format-Table 控制列宽

Controlling column widths with Format-Table

我正在尝试从列表中获取某些 PC 的上次重启时间。当我使用

foreach ($pc in $pclist) {
  Get-CimInstance -ClassName win32_operatingsystem -ComputerName $pc |
    select csname, lastbootuptime 
}

输出结果如下。

csname       lastbootuptime
------       --------------
CONFA7-L1-1A 7/15/2016 9:55:16 AM
CONFA7-L1-1F 5/31/2016 8:51:46 AM
CONFA7-L1-1G 6/18/2016 11:09:15 AM
CONFA7-L1... 6/26/2016 5:31:31 PM
CONFA7-L3... 7/24/2016 3:48:43 PM

这很整洁,但是如果PC名称很长,我看不到全名。 所以我流水线 Format-Table:

Get-CimInstance -ClassName win32_operatingsystem -ComputerName $pc |
  select csname, lastbootuptime |
  Format-Table  -HideTableHeaders 

这就是我得到的:

CONFA7-L1-1A 7/15/2016 9:55:16 AM



CONFA7-L1-1E 7/21/2016 12:58:16 PM



CONFA7-L1-1F 5/31/2016 8:51:46 AM

这里有两个问题。

  1. 没有标题。如果我删除 -HideTableHeaders,每个不需要的输出都会有标题。

  2. 中间有很多空格

基本上我只需要得到类似于第一个的输出,但不截断全名。我该如何解决这些问题?

总结和补充 PetSerAl and Ansgar Wiechers 的有用评论:

tl;dr

Get-CimInstance -ClassName win32_operatingsystem -ComputerName $pclist |
  Sort-Object CSName |
    Format-Table CSName, LastBootUpTime -AutoSize

-AutoSize 确保 CSName(计算机名称)列的宽度与它需要的一样宽 以完整显示所有值(除非这些值本身太长而无法放在一行中,在这种情况下必须使用 -Wrap - 见下文)。

Get-CimInstance 接受计算机名称的 array,因此不需要循环;然而,由于目标计算机被并行查询,返回的对象的顺序通常匹配计算机名称的输入顺序 - 这已得到纠正通过 Sort-Object CSName 调用。

控制个别列的宽度:

# Instead of a simple property name, 'prop1', pass a *hashtable*
# (@{ ... }`) with a 'width' entry to Format-Table
PS> [pscustomobject] @{ prop1='1234567890'; prop2='other' } |
       Format-Table -Property @{ e='prop1'; width = 5 }, prop2

prop1 prop2
----- -----
1234… other

注意:在 Windows PowerShell 中,您只会看到 12... 作为 t运行 分类值, 因为它使用 3 个单独的 . 个字符 来表示 t运行 阳离子;在 PowerShell [Core] 6+ 中,这已改进为使用 单个 字符,(水平省略号,U+2026)。

继续阅读以了解 有关 table 格式化的更多信息。


你的问题的核心是如何控制表格输出的输出列宽度,它适用于any cmdlet 的输出.

使用 Format-Table cmdlet(直接)进行表格输出,不是 Select-Object:目的Select-Object是创建自定义对象,不是格式化输出;如果此类对象(通常是没有预定义格式化视图的任何类型的实例)恰好具有 4 个或更少的属性,它们在幕后默认使用 Format-Table 格式化(但您不要申请选项);否则,它是 Format-List 被隐式使用。 谢谢,PetSerAl

  • Format-Table 总是将输出行限制在 可用屏幕宽度 ,这意味着:

    • 可能根本不会打印列。
    • 特别是打印的最后一列可能有其值 t运行cated,缺少的部分由 ... / 指示 - 尽管请注意 所有 打印列可以 有t运行 分类值,如下所述。
  • 如果要创建 更长的行,请将 Format-Table 的输出通过管道传输到 | Out-File -Width <int>| Out-String -Stream -Width <int>;请注意,如果将后者打印到屏幕上,行将 wrap(但额外的换行符不会成为数据的一部分)。

    • 警告:在 Windows PowerShell 上,请勿使用 -Width ([int]::MaxValue),因为table 格式化数据类型的格式化数据无条件地用 spaces 右填充到全宽,这会在输出文件中消耗过多的内存/space,你可能甚至 运行 内存不足。在 PowerShell Core 中,此问题已至少从 v6.1 开始修复。

    • Windows 上的替代方案(不适用于 Unix 类平台上的 PowerShell Core ) 是使用 [console]::BufferWidth = <column-count> 加宽 屏幕缓冲区 以允许不换行的更长行,但需要 水平滚动 .
      此外,在 Windows 上,它仅适用于常规控制台,不适用于 ISE。

  • 为了控制列宽 - 这间接决定了多少列将适合 - 使用以下参数:

    • -AutoSize ... 告诉 Format-Table 使列尽可能宽 以适合所有数据值,但请注意,这 会导致显示的列更少(通常情况下:更多)

    • -Wrap ... 使 列值跨越多行 ,如果需要,避免t运行阳离子;同样,这可以应用于 所有 谢谢, zett42.,而不仅仅是最后一个,即万一自动确定或固定列宽(通过 width 条目指定,如下所示)恰好超过特定值。

    • 指定自定义列宽,传递一个散列table width条目作为参数——所谓的Format-Table-Property参数;例如,以下示例将第一个输出列限制为 5 个字符:

        [pscustomobject] @{ prop1='1234567890'; prop2='other' } |
          Format-Table -Property @{ e='prop1'; width = 5 }, prop2
      
      • 如果出现 t运行cation,默认应用于值的 end,t运行cation 指标... / 总是占据 t运行 分类值的 最后 3 个字符(在 Windows PowerShell) / 仅 last 字符(在 PowerShell [Core] 6+ 中);在上面的示例中,prop1 值呈现为 12... / 1234… 总共 5 个字符。

      • 要 t运行cate start 值,您必须将列更改为 right-对齐,带有 alignment = 'right' 条目(默认为 'left''center' 是第三个选项;这两个 t运行cate end 个值)。

      • 如果你想保持 left 对齐,同时在 start 处仍然 t运行cating值,您必须在分配给 e (expression) 条目的脚本块 ({ ... }) 中使用自定义表达式:

        [pscustomobject] @{ prop1='1234567890'; prop2='other' } |
          Format-Table -Property @{ 
              n='prop1'; e={ $_.prop1 -replace '^.+(.{4})$', '…'}; width = 5 
            }, prop2
        
      • 注意:指定至少一个自定义宽度意味着您必须在-Property 参数,即使是那些不需要自定义宽度的参数。[1]

  • 警告,从 PowerShell 7.1 开始

    • 一个 bug 阻止自定义宽度生效,除非 first 列(也)有一个;此外,它 neverlast 列中生效 - 请参阅 GitHub issue #14676.

    • 正如zett42中指出和演示的那样,如果第一个 列是指定自定义宽度的计算列,其余行宽 均匀分布 在那些本身未指定列宽的其余列中 ,而不管这些列中的值实际有多宽 - 除非您还传递 -AutoSizeGitHub 问题 #14677.

      中讨论了这种意外行为

[1] 正如 zett42 指出的那样,如果所有列都具有相同的自定义宽度 ,您可以在技术上绕过此要求 ,因为将 属性-name 字符串传递给 e (Expression) hashtable 条目被解释为 通配符模式 ,因此字符串 '*' 匹配 所有 属性 名称;例如:
[pscustomobject] @{ a=1; b=2 } | Format-Table @{ e='*'; width=10 }

如果您想要 trim 超过一定长度的数据并手动指定列宽,您可以为每个 属性 属性传递一个 Width 属性。

例如,如果您希望数据如下所示:

Column 1    Column 2      Column 3      Column 4
--------    --------      --------      --------
Data        Lorem ip...   Lorem ip...   Important data

这是基本的 Format-Table 语法,带有显式属性列表:

$data | Format-Table -Property Col1, Col2, Col3, Col4 -AutoSize

我们可以添加一些 additional metadata to Property:

而不是只传递 属性 名称
$a = @{Expression={$_.Col1}; Label="Column 1"; Width=30}, 
     @{Expression={$_.Col2}; Label="Column 2"; Width=30}, 
     @{Expression={$_.Col3}; Label="Column 3"; Width=30}, 
     @{Expression={$_.Col4}; Label="Column 4"; Width=30}
$data | Format-Table -Property $a

注意:我意识到这在 mklement0 的更完整答案的底部有所介绍,但如果这是您的用例并且您正在快速滚动,我希望这有助于突出显示这个战略在高层次上