TAGS :Viewed: 18 - Published at: a few seconds ago

[ I would like to color highlight sections of a pipeline string according to a regex in Powershell ]

This is a question of technique, but as an exercise my intention is to write a PS to accept piped input, with a regex as a parameter, and highlight any text matching the regex.

The part I'm not able to find any info on is that it's easy to match text, capturing to a buffer, or to replace text. But I need to replace matched text with color control, the original text, then resume the previous color. I can't seem to find any way to generate color output other than with write-output, and can't do separate colors in a single write, which would mean:

-matching the regex

-write-host out all text prior to the match in default color, with -NoNewLine

-write-host the match, with -NoNewLine

-write-host the remainder

This seems messy, and gets even more messy if we want to support multiple matches. Is there a more eloquent way to do this?

Answer 1

Write-Host is the right way to do this. Use the .Index and .Length properties of the resulting Match object to determine where exactly the matched text is. You just need to be a bit careful keeping track of indices :)

This works for multiple matches, and is not terribly untidy IMO:

function ColorMatch
      [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
      [string] $InputObject,

      [Parameter(Mandatory = $true, Position = 0)]
      [string] $Pattern

   begin{ $r = [regex]$Pattern }
       $ms = $r.Matches($inputObject)
       $startIndex = 0

       foreach($m in $ms)
          $nonMatchLength = $m.Index - $startIndex
          Write-Host $inputObject.Substring($startIndex, $nonMatchLength) -NoNew
          Write-Host $m.Value -Back DarkRed -NoNew
          $startIndex = $m.Index + $m.Length

       if($startIndex -lt $inputObject.Length)
          Write-Host $inputObject.Substring($startIndex) -NoNew