Как раскрасить вывод PowerShell из Format-Table

Я пытаюсь раскрасить ОЗУ столбца красным, если значение больше 100 МБ:

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}}

8 ответов

Решение

Вы можете раскрасить строку, используя регулярное выражение...

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

Выход:

Введите описание изображения здесь

Начиная с PowerShell 5.1 или более поздней версии вы можете использовать escape-последовательности VT для добавления цветов в один столбец, но только если ваша консоль поддерживает escape-последовательности VT (например, Windows 10 Fall Creators Update, Linux или Mac, но не Windows 8 без эмулятора консоли как ConEmu).

Вот пример, форматирование которого указано в выражении, хотя его можно использовать и в файле 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

И результирующий вывод, обратите внимание, что ширина столбца выглядит хорошо, нет лишних пробелов от символов escape-последовательности.

Скриншот вывода каталога с цветными именами

Принятый ответ неверен, возможно раскрасить столбцы. Решением для получения условных цветов столбцов является использование Write-PSObject.

Вот несколько замечательных примеров с документированным кодом и пояснениями.

Из вышеуказанного ресурса:

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

Я обнаружил это через проблему GitHub, чтобы добавить цветовое форматирование в Format-Table, которая, кажется, является функцией, которую разработчики PowerShell хотели бы добавить в какой-то момент.

Быстрый ответ: ты не можешь. Можно использовать Write-Host с цветами, но нет "вывода" для отправки в format-table.

"Вывод" из Write-Host является побочным эффектом, который отправляет данные непосредственно на консоль, а не возвращает их вызывающей стороне, как стандартная функция.

В сочетании с комментарием @David Martin, вот ссылка с интересной функцией сопоставления с образцом формата-цвета.

Вот другая версия ответа Джейсона Ширка после нескольких лет использования PSStyle в PowerShell 7.4.

      # 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
    }
}

Да, вы можете использовать цвета ANSI Escape и иметь условные цвета:

      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"}}}

В этом примере показаны записи событий с чередующимися цветами фона строк (спасибо этому посту ). В зависимости от поля TimeCreated цвет текста будет синим (один месяц или меньше), желтым (одна неделя или меньше) или красным (сегодня). См. тему «ESC-код ANSI» в Википедии, чтобы узнать о цветовых escape-кодах.

      # 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

Вы можете установить модуль PsWrite

Цвет записи

у него также есть другие умные функции, такие как

Write-logstep

Запись-ProgressbarreColor

Другие вопросы по тегам