如何给PowerShell的Format-Table命令的输出结果添加颜色

25

如果该列的值大于100 MB,我将尝试使用红色对 RAM 列进行着色:

Get-Process | Format-Table @{ Label = "PID"; Expression={$_.Id}},
            @{ Label = "Name"; Expression={$_.Name}},
            @{ Label = "RAM (MB)"; Expression={[System.Math]::Round($_.WS/1MB, 1)}},
            @{ Label = "Responding"; Expression={$_.Responding}}

这里输入图片描述

我尝试使用Write-Host -nonewline,但结果是错误的。

Get-Process | Format-Table @{ Label = "PID"; Expression={$_.Id}},
            @{ Label = "Name"; Expression={$_.Name}},
            @{ Label = "RAM (MB)"; Expression={write-host -NoNewline $([System.Math]::Round($_.WS/1MB, 1)) -ForegroundColor red}},
            @{ Label = "Responding"; Expression={ write-host -NoNewline $_.Responding -fore red}}

Enter image description here


结果是什么?请发布屏幕截图。 - Victor Zakharov
1
阅读一下这篇文章,它可能会有所帮助:http://www.powershellmagazine.com/2013/06/20/an-example-when-using-write-host-makes-sense/ - David Martin
我提供了一个答案,但它只能对行进行着色,而不能对列进行着色。 - TheOptimusPrimus
1
你可以对不同的列进行着色,接受的答案已经不再正确,你需要使用Write-PSObject。请参见下面的我的答案。 - Bjorn
8个回答

44

从PowerShell 5.1或之后的版本开始,您可以使用VT转义序列为单个列添加颜色,但仅在控制台支持VT转义序列的情况下才能使用(例如Windows 10秋季创作者更新版、Linux或Mac,但不包括未安装控制台仿真器如ConEmu的Windows 8)。

以下是一个示例,其中格式规范化在表达式中指定,但是也可以在ps1xml文件中使用相同的规范化:

dir -Exclude *.xml $pshome | Format-Table Mode,@{
    Label = "Name"
    Expression =
    {
        switch ($_.Extension)
        {
            '.exe' { $color = "93"; break }
            '.ps1xml' { $color = '32'; break }
            '.dll' { $color = "35"; break }
           default { $color = "0" }
        }
        $e = [char]27
       "$e[${color}m$($_.Name)${e}[0m"
    }
 },Length

请注意输出结果,列的宽度看起来很好,没有转义序列字符造成的额外空格。

Screenshot of dir output with colored names


有一个关于(可能)16位支持的公告。这是否与此功能相关,还是另一件事? - stej
是的,一些终端支持256和24位颜色,我回答中的链接也描述了这一点。 - Jason Shirk
1
这是纯金啊,谢谢!我从中做了什么:https://gist.github.com/SeidChr/6dcae356760197d3d9147a3414829945 - Chris
如果有人想要声明魔术字符串和数字以提高可读性,请参见https://dev59.com/tGQo5IYBdhLWcg3wE74J。 - Zian Choy

20

被接受的答案是错误的,可以对列进行着色。获得条件列颜色的解决方案是使用Write-PSObject

这里有一些精彩的示例,带有记录的代码和解释。

来自上述资源:

Write-PSObject $servers -MatchMethod Exact -Column "Manufacture" -Value "HP" -ValueForeColor Yellow -ValueBackColor Red -RowForeColor White -RowBackColor Blue;

在此输入图片描述

我通过GitHub上格式化表格的颜色问题发现了这个,这似乎是PowerShell开发人员想要在某个时候添加的功能。


1
你的回答中的链接似乎不再指向正确的位置,只有 GitHub 问题仍然正确。 - skaravos

12

你可以使用正则表达式给上色...

filter colorize-row{

    Get-Process | Select-Object Id, Name, WS, Responding | foreach {

        # Print 'red' row if WS greater than 100 MB
        if([System.Math]::Round($_.WS/1MB,1) -match "^([0-9]|[0-9][0-9]|[1-9][0-9]?$|^100$)$"){
            [console]::ForegroundColor="white"; $_;
        } else {
            [console]::ForegroundColor="red"; $_;
        }
    }
}

colorize-row

输出:

在此输入图片描述


1
有没有一种方法可以像使用Format-Table时那样进行格式化?我尝试了@{n="<heading>"; e={$_.<value>}; a="left"}语法,但它不起作用。 - Adrian
这个答案已经不正确了,你可以给列着色,看看我的回答。 - Bjorn

4
快速的答案是你不能。使用Write-Host可以使用颜色,但没有“输出”可以发送到format-table。
“output”来自Write-Host是一种副作用,会将数据直接发送到控制台,而不是像标准函数一样将其返回给调用者。
结合@David Martin的评论,这里有一个链接,其中包含一个有趣的模式匹配格式颜色函数。

2
这是几年后使用 PowerShell 7.4 中的 PSStyle 后,Jason Shirk's answer 的另一种版本。

enter image description here

# Create a dummy data table with three columns: Name, Age, and Occupation
$data = @(
    [PSCustomObject]@{Name = 'Alice'; Age = 25; Occupation = 'Teacher' }
    [PSCustomObject]@{Name = 'Bob'; Age = 30; Occupation = 'Engineer' }
    [PSCustomObject]@{Name = 'Charlie'; Age = 35; Occupation = 'Doctor' }
    [PSCustomObject]@{Name = 'David'; Age = 40; Occupation = 'Lawyer' }
    [PSCustomObject]@{Name = 'Eve'; Age = 45; Occupation = 'Artist' }
)

$PSStyle.Formatting.TableHeader = "$($PSStyle.Foreground.FromRGB(218,112,214))"

$data | Format-Table @{
    Label      = 'Name'
    Expression =
    { switch ($_.Name) {
            { $_ } { $color = "$($PSStyle.Foreground.FromRGB(255,255,49))$($PSStyle.Blink)" } # Use PSStyle to set the color
        }
        "$color$($_.Name)$($PSStyle.Reset)" # Use PSStyle to reset the color
    }
}, @{
    Label      = 'Age'
    Expression =
    { switch ($_.age) {
            { $_ -gt 30 } { $color = "$($PSStyle.Foreground.FromRGB(255,20,147))$($PSStyle.Blink)" } # Use PSStyle to set the color
        }
        "$color$($_.age)$($PSStyle.Reset)" # Use PSStyle to reset the color
    }
}, @{
    Label      = 'Occupation'
    Expression =
    { switch ($_.Occupation) {
            { $_ } { $color = "$($PSStyle.Foreground.FromRGB(152,255,152))$($PSStyle.Blink)" } # Use PSStyle to set the color
        }
        "$color$($_.Occupation)$($PSStyle.Reset)" # Use PSStyle to reset the color
    }
}

1

是的,你可以使用 ANSI Escape colors 并且根据条件设置颜色:

Get-Process | Format-Table @{ Label = "PID"; Expression={$_.Id}},
        @{ Label = "Name"; Expression={$_.Name}},
        @{ Label = "RAM (MB)"; Expression={if($_.WS/1MB -gt 100){"$([char]27)[0;31m$([System.Math]::Round($_.WS/1MB, 1))$([char]27)[0m"}else{"$([char]27)[0;32m$([System.Math]::Round($_.WS/1MB, 1))$([char]27)[0m"}}},
        @{ Label = "Responding"; Expression={if($_.Responding -eq $true){"$([char]27)[0;32m$($_.Responding)$([char]27)[0m"}else{"$([char]27)[0;31m$($_.Responding)$([char]27)[0m"}}}

0

0
这个例子展示了事件记录,行的背景颜色交替显示(感谢this post)。 根据TimeCreated字段,文本颜色将为蓝色(一个月或更短时间内),黄色(一周或更短时间内)或红色(今天)。 请参考维基百科上的“ANSI Escape code”主题以获取颜色转义代码。
# constants
$e=[char]27                                             # escape character
[string]$_Reset     = $($e+"[0m")
[string]$_bSapphire1= $($e+"[48;2;1;36;86m")        # ESC[48;2;r;g;bm Select RGB background colour
[string]$_bSapphire2= $($e+"[48;2;3;55;155m")
[string]$_fBRed     = $($e+"[91m")
[string]$_fBYellow  = $($e+"[93m")
[string]$_fBCyan    = $($e+"[96m")
$Today              = [datetime]::today
$OneWeek            = $Today.AddDays(-7)
$OneMonth           = $Today.AddDays(-30)
# variable
[ref]$bToggle       = $True                         # makes the background colour of the row alternate
# script block
$ExtractScript={
    param([array]$Events,[enum]$Level)
    $Events|
    Where-Object { $Level -eq $_.Level }|
    Sort-Object -Property @{ Expression="ProviderName"; Ascending=$True },
                          @{ Expression="TimeCreated" ; Ascending=$True }|
    Format-Table @{
            Label="TimeCreated"
            Expression= {
                # rows have an alternating background colour
                if($bToggle.Value) { $bcolour=[string]::copy($_bSapphire1) } else { $bcolour=[string]::copy($_bSapphire2) }
                $bToggle.Value = $(-not $bToggle.Value)
                
                # TimeCreated has effect on the foreground colour of the row 
                $fcolour = [string]::copy($_Reset)
                if( $OneMonth -lt $_.TimeCreated ) { $fcolour = [string]::copy($_fBCyan) }
                if( $OneWeek  -lt $_.TimeCreated ) { $fcolour = [string]::copy($_fBYellow) }
                if( $Today    -lt $_.TimeCreated ) { $fcolour = [string]::copy($_fBRed) }
                $($fcolour+$bcolour+$("{0:d} {0:HH}:{0:mm}:{0:ss}" -f $($_.TimeCreated)))
            }
            Alignment='Right'
        },
        ProviderName,
        ID,
        @{
            Name='Level'
            Expression={$_.LevelDisplayName}
            Alignment='Right'
        },
        @{
            Name='Message'
            Expression={
                # Colours are reset
                $($_.Message+$_Reset)
            }
        }       
}
# code
$EventArray=Get-WinEvent -LogName System -MaxEvents 10000
& $ExtractScript -Events $EventArray -Level $([System.Diagnostics.Eventing.Reader.StandardEventLevel]::Error)
$($_Reset+"Legend:")|Out-Default
$($_fBCyan+"After "+$("{0:d} {0:HH}:{0:mm}:{0:ss}" -f $OneMonth))|Out-Default
$($_fBYellow+"After "+$("{0:d} {0:HH}:{0:mm}:{0:ss}" -f $OneWeek))|Out-Default
$($_fBRed+"Today")|Out-Default   
$_Reset|Out-Default

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接