I would like to highlight the highlighted sections of the pipeline string according to the regular expression in Powershell

This is a technical issue, but as an exercise, I intend to write a PS to accept the input with channels, with a regular expression as a parameter, and select any text that matches the regular expression.

The part I cannot find information for is that it easily matches text, captures a buffer, or replaces text. But I need to replace the corresponding text with the color, the original text, and then resume the previous color. It seems I cannot find any way to generate an output color other than write-output, and cannot make separate colors in one record, which would mean:

regular regular expression

-write-host print all text before the default color match, using -NoNewLine

-write-host match, with -NoNewLine

-write-host remainder

It seems dirty and gets even more dirty if we want to maintain multiple matches. Is there a more eloquent way to do this?

+4
source share
3 answers

Write-Host is the right way to do this. Use the .Index and .Length properties of the resulting Match object to determine where the text exactly matches. You just need to keep a little eye on the performance :)

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

 function ColorMatch { param( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [string] $InputObject, [Parameter(Mandatory = $true, Position = 0)] [string] $Pattern ) begin{ $r = [regex]$Pattern } process { $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 } Write-Host } } 
+5
source

This is a continuation of the Latkin response. Here I am extending the Match object so that it can be processed more easily for this and other purposes.

 function Split-Match { param([Parameter(Mandatory = $true)] $match ) $sections = @() $start = 0 $text = $m.Line foreach ($m in $match.Matches) { $i = $m.Index $l = $m.Length $sections += $false, $text.Substring($start, $i - $start) $sections += $true, $text.Substring($i, $l) $start = $i + $l } $sections += $false, $text.Substring($start) $match | Add-Member -Force Sections $sections $match } function Write-Match { param([Parameter(Mandatory = $true)] $match ) $fg = "White" $bg = "Black" foreach($s in $match.Sections) { if ($s.GetType() -eq [bool]) { if ($s) { $fg = "White" $bg = "Red" } else { $fg = "White" $bg = "Black" } } else { Write-Host -NoNewline -ForegroundColor $fg -BackgroundColor $bg $s } } Write-Host } $string = @' Match this A Not this B Not this C But this A '@ $m = $string | select-string -CaseSensitive -AllMatches "A" $m = Split-Match $m Write-Match $m 

output

0
source

As an alternative, I found that using ANSI / VT100 formatting is easier and does exactly what I need with a much wider range of colors:

 $esc=[char]27 $fileContents="abc455315testing123455315abc" $keywordSearch="testing123" $fileContents -replace $keywordSearch,"$esc[38;2;0;200;255m$keywordSearch$esc[0m" 

Note that this only works in the PowerShell console window, not in PowerShell ISE. This wikipedia page was also helpful; in particular, this line regarding color choices:

ESC [38; 2; ⟨R⟩; ⟨G⟩; ⟨B⟩ m RGB foreground color selection

0
source

Source: https://habr.com/ru/post/1436464/


All Articles