powershellcolorsgrephighlightselect-string

How to highlight the properties of Select-String results with different colors?


I'm trying to mimic grep using powershell, and would like to improve the readability of output of the Select-String, by giving different colors to the different properties.


# Select-String -Path <sometext-file> -AllMatches -Pattern <regEx>
function nix_grep {
    if( $args.count -eq 0) { 
        Write-Host -f Red "Error: " -Non; Write-Host "Please provide a RegEx argument to grep." 
        Write-Host -f DarkYellow "Usage: grep <file/path> <RegEx>" 
    } else {
        if ($args.count -eq 2) { Select-String -Path $args[0] -AllMatches -Pattern $args[1] }
    } 
}

Set-Alias -Name grep -Value nix_grep 


grep ".\zx_ASCII.txt" "ABCD"
# zx_ASCII.txt:1:1234 5678 ABCD EFGH
# zx_ASCII.txt:7:!"#$%&'()*+,-./0ABCD


grep ".\zx_ASCII.txt" "ABCD" | select Filename, LineNumber, pattern, Line

# Filename     LineNumber Pattern Line
# --------     ---------- ------- ----
# zx_ASCII.txt          1 ABCD    1234 5678 ABCD EFGH
# zx_ASCII.txt          7 ABCD    !"#$%&'()*+,-./0ABCD

Q: How can I output these with different colors?
(..and still have the matched pattern inverted.)


Solution

  • This was a tricky exercise, but the result was worthwhile and now providing a very good looking grep result.

    function ansi-reverse {
        param(
            [Parameter(Mandatory = $true, Position=0)] [string] $txt,   # raw text string
            [Parameter(Mandatory = $true, Position=1)] [string] $pat    # Pattern string
        )
        
        $ESC = "$([char] 27)"   # ANSI ESC (0x1b)
        $RES = "`e[0m"          # ANSI Reset ()
        $RON = "`e[7m"          # Reverse
        $ROF = "`e[27m"         # ReverseOff
        $RED = "`e[91m"         # BrightRed
        $GRY = "`e[90m"         # BrightBlack / "DarkGray"
    
        # Replace text pattern with ANSI Reversed version (and using capture group for case preserve)
        # https://stackoverflow.com/a/40683667/1147688
        $txt = "$txt" -replace "($pat)", "$RED`$1$GRY"      # Using: BrightRed
    
        Return "$txt"
    }
    
    function print-color {
        param( 
            [Parameter(Mandatory = $true, Position=0)] [string] $i,     # Filename
            [Parameter(Mandatory = $true, Position=1)] [string] $j,     # Linenumber
            [Parameter(Mandatory = $true, Position=2)] [string] $k,     # Line
            [Parameter(Mandatory = $true, Position=3)] [string] $p      # Pattern
        )
        
        $fn = " {0}  " -f $i
        $nn = ": {0,-5}: " -f $j
        $ln = (ansi-reverse "$k" "$p")
        
        Write-Host -f DarkYellow "$fn" -non
        Write-Host -f Yellow "$nn" -non
        Write-Host -f DarkGray "$ln"
    }
    
    function nix_grep {
        if( $args.count -eq 0) { 
            Write-Host -f Red "Error: " -Non; Write-Host "Please provide a RegEx argument to grep." 
            Write-Host -f DarkYellow "Usage: grep <file/path> <RegEx>"  
        } else {
            if ($args.count -eq 2) { 
                $A = Select-String -Path $args[0] -AllMatches -Pattern $args[1] 
                $A | select Filename, LineNumber, Pattern, Line | %{ 
                    $i = $_.Filename
                    $j = $_.Linenumber
                    $k = $_.Line
                    $p = $_.Pattern
                    print-color "$i" "$j" "$k" "$p"
                }
            }
        } 
    }
    
    

    The output becomes:

    enter image description here


    Extra Credit: