是否可以在 powershell 中为 grep 输出添加颜色?

是否可以在 powershell 中为 grep 输出添加颜色?

我想在 Windows 上运行一个 java 应用程序,但根据匹配的文本为一些输出行涂上不同的背景和前景色。

使用 Windows powershell 可以实现吗?我该怎么做?

答案1

  • 短的答案很简单

  • 长的答案是一切皆有可能, 但 ...

不幸的是,任何颜色和字符串操作电源外壳非常麻烦。原因是开箱即用的 Windows 控制台终端使用自己的方式进行着色,而不是使用转义序列进行着色。* [见注释!] 这(据我所知)总是需要使用Write-Host。因此,任何颜色操作很快就会变得适得其反,因为它们通常需要大量的 Windows工程,以解决过早输出且无法轻松地将颜色存储在字符串变量中的问题。

无论如何,这里有一个更有用的解决方案来突出显示不安全 ExecutionPolicy设置。(基本上是安东尼答案的一个工作修改。)这里使用了一个预设搜索条件(作为数组),但可能可以被修改并转换为适当的ColorGrep(<string>)函数。

# To get the ExecutionPolicy List
Function Get-MyPolicy {
    $ZZ_EPOL = ((Get-ExecutionPolicy -List) | Format-Table -hideTableHeader @{Label="ExePol"; e={"        {0,-16}: {1,-20}" -f $_.Scope, $_.ExecutionPolicy}})
    $ZZ_EPOL
}

# Colorize the unsafe Execution Policies
Function ColorMatch {
    Process {
        $polkeys = @("Bypass","Unrestricted")
        foreach ($line in $_) {
            foreach ($i in $polkeys) {
                $res =''
                If ($line -match $i) {
                    $iPosition  = $line.IndexOf($i)         # start position of "grep phrase"
                    $iLength    = $i.Length                 # length of grep phrase
                    $iEnd       = $iPosition + $iLength     # end of grep phrase
                    $LineLength = $line.Length              # length of line
                    $iComplete  = $LineLength - $iEnd       # length of characters to complete the line

                    $res  = (Write-Host $line.Substring(0, $iPosition) -NoNewline)
                    $res += (Write-Host $line.Substring($iPosition, $iLength) -ForegroundColor Red -NoNewline)
                    $res += (Write-Host $line.Substring($iEnd, $iComplete) -NoNewline)
                    Write-Host $res
                    break  # There's only one match per line
                }
            } # END foreach 2
            If (($res -eq '') -and ($line -ne '')) { 
                Write-Host $line 
            } 
        } # END foreach 1
    } # END process
}

要运行它,请使用:
Get-MyPolicy | Out-String -stream | ColorMatch

输出为:

在此处输入图片描述

最后,如果您需要传入其他字符串,则可能需要解析$line$_输入以将字符串分成几行。由于脚本假设每行只有一个匹配项。这就是为什么Out-String用来。

笔记:
最近Windows 10添加了一些色彩能力。然而,已经有几十个第三方控制台解决方案可以做到这一点。

答案2

正如下面的简单示例一样,您可以尝试匹配输出并相应地着色。

$Items = @("Find","Matching","Item")
$colItem = "Matching"

foreach ($i in $Items) {

    if ($i -match $colItem){
      write-host  $i -foregroundcolor magenta -BackgroundColor yellow}
     else {write-host $i}
}

- 编辑 -

进一步举一个粗略的工作示例(仅使用 ps4 检查)“grepping”Phrase PowerShell 的 Get Help cmdlet 输出。将为每行第一个短语提供彩色输出

 Function Coloured-Output {
    Process { 
       $i = "PowerShell"
       If ($_ -match $i){
          $iPosition = $_.IndexOf($i)       # start position of "grep phrase"
          $iLength = $i.Length              # length of grep phrase
          $iEnd = $iPosition + $iLength     # end of grep phrase
          $LineLength = $_.Length           # length of line
          $iComplete = $LineLength - $iEnd  # length of characters to complete the line
          Write-Host $_.Substring(0,$iPosition) -NoNewline
          Write-Host $_.Substring($iPosition,$iLength) -Foregroundcolor Blue -BackgroundColor cyan -NoNewline
          Write-Host $_.Substring($iEnd,$iComplete)
       }
       else {write-host $_ }
    } # End of Process
} # End of Function
    
$SplitThis = Get-Help

   $SplitThis -split ("`n")  | Out-String -stream | Coloured-Output

########## 已编辑,其他人提供了最佳解决方案 ############

最佳解决方案https://ridicurious.com/2018/03/14/highlight-words-in-powershell-console/与我自己的解决方案相比,这是对原始问题的更好、更全面的回答。

    Function Trace-Word
{
    [Cmdletbinding()]
    [Alias("Highlight")]
    Param(
            [Parameter(ValueFromPipeline=$true, Position=0)] [string[]] $content,
            [Parameter(Position=1)] 
            [ValidateNotNull()]
            [String[]] $words = $(throw "Provide word[s] to be highlighted!")
    )
    
Begin
{
    
    $Color = @{       
                0='Yellow'      
                1='Magenta'     
                2='Red'         
                3='Cyan'        
                4='Green'       
                5 ='Blue'        
                6 ='DarkGray'    
                7 ='Gray'        
                8 ='DarkYellow'    
                9 ='DarkMagenta'    
                10='DarkRed'     
                11='DarkCyan'    
                12='DarkGreen'    
                13='DarkBlue'        
    }

    $ColorLookup =@{}

    For($i=0;$i -lt $words.count ;$i++)
    {
        if($i -eq 13)
        {
            $j =0
        }
        else
        {
            $j = $i
        }

        $ColorLookup.Add($words[$i],$Color[$j])
        $j++
    }
    
}
Process
{
$content | ForEach-Object {

    $TotalLength = 0
           
    $_.split() | `
    Where-Object {-not [string]::IsNullOrWhiteSpace($_)} | ` #Filter-out whiteSpaces
    ForEach-Object{
                    if($TotalLength -lt ($Host.ui.RawUI.BufferSize.Width-10))
                    {
                        #"TotalLength : $TotalLength"
                        $Token =  $_
                        $displayed= $False
                        
                        Foreach($Word in $Words)
                        {
                            if($Token -like "*$Word*")
                            {
                                $Before, $after = $Token -Split "$Word"
                          
                                    
                                #"[$Before][$Word][$After]{$Token}`n"
                                
                                Write-Host $Before -NoNewline ; 
                                Write-Host $Word -NoNewline -Fore Black -Back $ColorLookup[$Word];
                                Write-Host $after -NoNewline ; 
                                $displayed = $true                                   
                                #Start-Sleep -Seconds 1    
                                #break  
                            }

                        } 
                        If(-not $displayed)
                        {   
                            Write-Host "$Token " -NoNewline                                    
                        }
                        else
                        {
                            Write-Host " " -NoNewline  
                        }
                        $TotalLength = $TotalLength + $Token.Length  + 1
                    }
                    else
                    {                      
                        Write-Host '' #New Line  
                        $TotalLength = 0 

                    }

                        #Start-Sleep -Seconds 0.5
                    
    }
    Write-Host '' #New Line               
}
}
end
{    }
# the last bracket
}


#Trace-Word -content (Get-Content iis.log) -words "IIS", 's', "exe", "10", 'system'

相关内容