Цветные слова в формате сценария powershell-вывод таблицы
можно ли окрашивать только определенные слова (не полные строки) для вывода powershell с помощью format-table. Например, этот скрипт рекурсивно сканирует папку для строки, а затем выводит результат с помощью format-table.
dir -r -i *.* | Select-String $args[0] |
format-table -Property @{label="Line #"; Expression={$_.LineNumber}; width=6},
Path, Line -wrap
было бы неплохо иметь возможность форматировать слово, которое мы ищем, определенным цветом, чтобы вы могли точно видеть, где оно было найдено в строке.
4 ответов
вы могли бы трубу таблицы в Out-String
, затем напишите строку по частям, используя Write-Host
С -NoNewLine
переключатель.
что-то вроде этого:
filter ColorWord {
param(
[string] $word,
[string] $color
)
$line = $_
$index = $line.IndexOf($word, [System.StringComparison]::InvariantCultureIgnoreCase)
while($index -ge 0){
Write-Host $line.Substring(0,$index) -NoNewline
Write-Host $line.Substring($index, $word.Length) -NoNewline -ForegroundColor $color
$used = $word.Length + $index
$remain = $line.Length - $used
$line = $line.Substring($used, $remain)
$index = $line.IndexOf($word, [System.StringComparison]::InvariantCultureIgnoreCase)
}
Write-Host $line
}
Get-Process| Format-Table| Out-String| ColorWord -word 1 -color magenta
мне нравится Rynant'ы подход. Вот альтернативная реализация, использующая -split
вместо IndexOf
:
filter ColorWord( [string]$word, [ConsoleColor]$color ) {
$later = $false
$_ -split [regex]::Escape( $word ) | foreach {
if( $later ) { Write-Host "$word" -NoNewline -ForegroundColor $color }
else { $later = $true }
Write-Host $_ -NoNewline
}
Write-Host
}
Split включает пустые строки, если строка начинается или заканчивается данным словом, следовательно, дополнительная логика" если не первая".
Edit: следуя комментарию Райнанта, вот еще одна реализация, которая поддерживает как простые, так и регулярные выражения:
filter ColorPattern( [string]$Pattern, [ConsoleColor]$Color, [switch]$SimpleMatch ) {
if( $SimpleMatch ) { $Pattern = [regex]::Escape( $Pattern ) }
$split = $_ -split $Pattern
$found = [regex]::Matches( $_, $Pattern, 'IgnoreCase' )
for( $i = 0; $i -lt $split.Count; ++$i ) {
Write-Host $split[$i] -NoNewline
Write-Host $found[$i] -NoNewline -ForegroundColor $Color
}
Write-Host
}
в вывод из следующих примеров показывает разницу:
PS> '\d00\d!' | ColorPattern '\d' 'Magenta' -Simple
\d00\d!
PS> '\d00\d!' | ColorPattern '\d' 'Magenta'
\d00\d!
Я люблю ответ @Ryant дал. У меня есть модифицированная версия, которая может использоваться для окрашивания нескольких слов в выходе, передавая массивы или слова и цвета. Фокус в том, что вы должны разделить входной текст на строки на основе разделителя новой строки.
filter ColorWord2 {
param(
[string[]] $word,
[string[]] $color
)
$all = $_
$lines = ($_ -split '\r\n')
$lines | % {
$line = $_
$x = -1
$word | % {
$x++
$item = $_
$index = $line.IndexOf($item, [System.StringComparison]::InvariantCultureIgnoreCase)
while($index -ge 0){
Write-Host $line.Substring(0,$index) -NoNewline
Write-Host $line.Substring($index, $item.Length) -NoNewline -ForegroundColor $color[$x]
$used =$item.Length + $index
$remain = $line.Length - $used
$line =$line.Substring($used, $remain)
$index = $line.IndexOf($item, [System.StringComparison]::InvariantCultureIgnoreCase)
}
}
Write-Host $line
} }
и будет выполняться следующим образом
Get-Service | Format-Table| Out-String| ColorWord2 -word 'Running','Stopped' -color 'Green','Red'
#$VerbosePreference = 'continue'
$VerbosePreference = 'silent'
filter ColorPattern {
param ([object]$colors, [switch]$SimpleMatch)
[string]$line = $_
$collection = New-Object 'System.Collections.Generic.SortedDictionary[int, pscustomobject]'
$RegexOptions = [Text.RegularExpressions.RegexOptions]::IgnoreCase.value__ + [Text.RegularExpressions.RegexOptions]::Singleline.value__
if ($SimpleMatch){
$patternMatches = $colors.keys | % {[regex]::Escape($_)}
$reference = 'Value'
} else {
$patternMatches = $colors.keys
$reference = 'Pattern'
}
# detect RegEx matches and add to collection object
Write-Verbose "'$line'"
$measureparsing