【问题标题】:Format-Table set column width depending on the output buffer widthFormat-Table 根据输出缓冲区宽度设置列宽
【发布时间】:2021-01-25 12:53:58
【问题描述】:

我有一个 cmdlet,它使用 Format-Table 输出可能很长的字符串(例如注册表路径)。我想将每列宽度设置为输出缓冲区宽度除以列数。

例子:

function Write-Something {
    [CmdletBinding()] param()

    $o = [pscustomobject]@{ a = 'A' * 100; b = 'B' * 100 }
    
    $columnWidth = [int]( $PSCmdlet.Host.UI.RawUI.BufferSize.Width / 2 )
    $o | Format-Table @{ e = 'a'; width = $columnWidth }, @{ e = 'b'; width = $columnWidth } -wrap
}

这非常适用于控制台输出,它会产生如下输出:

一个 - - 啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊 啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊 AAAAAAAAAAAA BBBBBBBBBBBB

问题

当我使用Out-StringOut-FileWidth 参数指定不同的输出缓冲区宽度时,格式不会改变,它仍将基于控制台缓冲区宽度。

Write-Something | Out-File test.txt -Width 200

这会产生与上面相同的输出,而预期的输出应该是宽度为 100 的列,并且不会发生换行。

如何从我的 cmdlet 中获取由 Out-StringOut-FileWidth 参数设置的实际输出缓冲区宽度?

【问题讨论】:

    标签: powershell


    【解决方案1】:

    问题是您已经在 Write-Something cmdlet 中修复了宽度。执行此操作的 PowerShell 方法是让您的 cmdlet 输出未格式化的数据对象,并用您自己的控制输出宽度的 cmdlet 替换 Out-File。

    function Write-Something {
        [CmdletBinding()] param()
    
        $o = [pscustomobject]@{ a = 'A' * 100; b = 'B' * 100 }
        Write-Output $o
    }
    
    function Out-Something {
        [CmdletBinding()] param(
            [Parameter(ValueFromPipeline=$true)]
            [psobject]$InputObject,
            [Parameter(Position=1)]
            [String]$FilePath,
            [Parameter(Position=2)]
            [int]$Width
        )
    
        $columnWidth = [int]( $Width / 2 )
        $InputObject | Format-Table @{ e = 'a'; width = $columnWidth }, @{ e = 'b'; width = $columnWidth } -Wrap | ` 
            Out-File -FilePath $FilePath -Width $Width
    }
    
    Write-Something | Out-Something test.txt -Width 200
    

    【讨论】:

    • 这是一个实用的解决方法。对我来说,这需要Format-Table 功能请求能够指定相对列宽。例如。 Format-Table @{ e = 'a'; width = '50%' }, @{ e = 'b'; width = '50%' }.
    【解决方案2】:

    简单的解决方法

    如果第一列具有固定宽度,则其余列将均匀分布在剩余宽度上。

    $o = [pscustomobject]@{ a = 'A' * 100; b = 'B' * 100 }
        
    $o | Format-Table @{ e = ' '; width = 1 }, 'A', 'B' -wrap
    

    输出:

    一个 - - - 啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊 啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊 AAAAAAAAAAAAAAAA BBBBBBBBBBBBBBBB

    这会创建一个看起来有点尴尬的空列。在实践中,我们可能有适合第一个固定宽度列的有用数据,例如。 G。 为每一行编号

    $o = 1..2 | ForEach-Object { [pscustomobject]@{ a = 'A' * 100; b = 'B' * 100 } }
    
    $i = 0
    $numbered = { $i; ( Get-Variable i -Scope 1 ).Value++ }
    
    $o | Format-Table @{ n = '#'; width = 3; e = $numbered }, 'A', 'B' -wrap
    

    输出:

    # a b - - - 1 啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊 啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊 AAAAAAAAAAAAAAAA BBBBBBBBBBBBBBBB 2 啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊 啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊 AAAAAAAAAAAAAAAA BBBBBBBBBBBBBBBB

    带编号的列实际上使包含包裹列的表格更易于阅读,因为更容易查看每行的开始位置。

    我们也可以像这样从输出中删除空列

    $o | Format-Table @{ e = ' '; width = 1 }, 'A', 'B' -wrap |
        Out-String -Stream | ForEach-Object { $_ -replace '^[-\s]\s' }
    

    More Format-Table shenanigans

    【讨论】:

    • 正如我们在链接答案的上下文中所讨论的,这种均匀分布的行为,在 PowerShell 7.1 中仍然存在,似乎是偶然的,应该考虑到 默认 行为一个错误(作为一个功能,它需要通过一个假设的未来开关opt-in) - 请参阅GitHub issue #14677
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-29
    • 2016-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-27
    相关资源
    最近更新 更多