Created
April 29, 2024 05:33
-
-
Save earthdiver/0dbb016790ba531fb9e3e8002d7b671a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <# | |
| .SYNOPSIS | |
| A grep-like tool with a color highlighting feature. | |
| .DESCRIPTION | |
| This function searches for text patterns in input strings. | |
| If input is an object, it is converted to a string prior to processing. | |
| Matched characters are highlighted. | |
| '(some command) | Select-MatchedString -Pattern <regex>' | |
| is similar to | |
| '(some command) | Output-String -Stream | Select-String -Pattern <regex> -AllMatch -CaseSensitive' | |
| with PowerShell 7.X, in which Select-String cmdlet has a highlighting feature. | |
| .PARAMETER Pattern | |
| Specifies the text patterns to find. Type a string or regular expression. | |
| If you type a string, use the SimpleMatch parameter. | |
| .PARAMETER BackgroundColor | |
| Specifies the background color for matches. (Alias: -bc) | |
| The default value is "Blue". | |
| .PARAMETER CapturegroupColor | |
| Specifies the foreground color for capture-group matches. (Alias: -cc) | |
| The default value is "Red". | |
| .PARAMETER ForegroundColor | |
| Specifies the foreground color for matches. (Alias: -fc) | |
| The default value is "White". | |
| .PARAMETER Group | |
| Specifies the name or number of capture group. (Alias: -g) | |
| The default value is "0". | |
| .PARAMETER ECMAScript | |
| Enables ECMAScript-compliant behavior. (Alias: -e) | |
| .PARAMETER IgnoreCase | |
| Makes matches case-insensitive. By default, matches are case-sensitive. (Alias: -i) | |
| .PARAMETER InputObject | |
| Specifies the text to be searched. (Alias: -io) | |
| .PARAMETER PassThru | |
| Outputs all lines, including ones that do not match. (Alias: -p) | |
| .PARAMETER Narrow | |
| Converts wide characters into narrow ones internally. (Alias: -n) | |
| Useful when you don't want to distinguish between narrow and wide characters. | |
| .PARAMETER SimpleMatch | |
| Uses a simple match rather than a regular expression match. (Alias: -s) | |
| .NOTES | |
| Author: earthdiver1 | |
| Version: V1.03 | |
| Licensed under a Creative Commons Attribution-ShareAlike 4.0 International License. | |
| #> | |
| Function Select-MatchedString { | |
| [Alias('hGrep')] | |
| Param( | |
| [Parameter(Mandatory=$True)][String]$Pattern, | |
| [Alias("g")][String]$Group = "0", | |
| [Alias("e")][Switch]$ECMAScript, | |
| [Alias("i")][Switch]$IgnoreCase, | |
| [Alias("w")][Switch]$Narrow, | |
| [Alias("n")][Switch]$Number, | |
| [Alias("p")][Switch]$PassThru, | |
| [Alias("s")][Switch]$SimpleMatch, | |
| [Alias("bc")][ConsoleColor]$BackgroundColor = "Blue", | |
| [Alias("cc")][ConsoleColor]$CapturegroupColor = "Red", | |
| [Alias("fc")][ConsoleColor]$ForegroundColor = "White", | |
| [Parameter(ValueFromPipeline=$True)][Alias("io")][PSObject]$InputObject | |
| ) | |
| Begin { | |
| try { | |
| if ( -not $Pattern ) { break } | |
| if ( $Narrow ) { | |
| Add-Type -AssemblyName "Microsoft.VisualBasic" | |
| $Pattern = [Microsoft.VisualBasic.Strings]::StrConv($Pattern,[Microsoft.VisualBasic.VbStrConv]::Narrow) | |
| } | |
| if ( $SimpleMatch ) { $Pattern = [regex]::Escape( $Pattern ) } | |
| if ( $Number ) { | |
| $line = 0 | |
| $width = $host.UI.RawUI.BufferSize.Width - 7 | |
| } else { | |
| $width = $host.UI.RawUI.BufferSize.Width - 1 | |
| } | |
| $regexOptions = "Compiled" | |
| if ( $ECMAScript ) { $regexOptions += ", ECMAScript" } | |
| if ( $IgnoreCase ) { $regexOptions += ", IgnoreCase" } | |
| $Regex = New-Object Text.RegularExpressions.Regex $Pattern, $regexOptions | |
| $process_block = { | |
| Process { | |
| $line++ | |
| $i = 0 | |
| if ( $Narrow ) { $_ = [Microsoft.VisualBasic.Strings]::StrConv($_,[Microsoft.VisualBasic.VbStrConv]::Narrow) } | |
| $match = $Regex.Match($_,$i) | |
| $m = $match.Groups[$Group] | |
| if (-not $PassThru -and -not $m.Success) { return } | |
| if ( $Number ) { Write-Host $("{0,5}:" -F $line) -NoNewline } | |
| if ( $Group -eq "0" ) { | |
| while ($m.Success) { | |
| if ( $m.Index -ge $_.Length ) { break } | |
| if ( $m.Length -gt 0 ) { | |
| Write-Host $_.SubString($i, $m.Index - $i) -NoNewline | |
| Write-Host $m.Value -BackgroundColor $BackgroundColor -ForegroundColor $ForegroundColor -NoNewline | |
| $i = $m.Index + $m.Length | |
| } else { | |
| Write-Host $_.SubString($i, $m.Index - $i + 1) -NoNewline | |
| $i = $m.Index + 1 | |
| } | |
| $m = $Regex.Match($_,$i).Groups[0] | |
| } | |
| } else { | |
| while ( $m.Success ) { | |
| if ( $m.Index -ge $_.Length ) { break } | |
| $m0 = $match.Groups[0] | |
| if ( $m0.Length -gt 0 ) { | |
| Write-Host $_.SubString($i, $m0.Index - $i) -NoNewline | |
| Write-Host $_.SubString($m0.Index, $m.Index - $m0.Index) ` | |
| -BackgroundColor $BackgroundColor -ForegroundColor $ForegroundColor -NoNewline | |
| Write-Host $m.Value -BackgroundColor $BackgroundColor -ForegroundColor $CapturegroupColor -NoNewline | |
| $i = $m0.Index + $m0.Length | |
| $ii = $m.Index + $m.Length | |
| Write-Host $_.SubString($ii, $i - $ii) ` | |
| -BackgroundColor $BackgroundColor -ForegroundColor $ForegroundColor -NoNewline | |
| } else { | |
| Write-Host $_.SubString($i, $m0.Index - $i + 1) -NoNewline | |
| $i = $m0.Index + 1 | |
| } | |
| $match = $Regex.Match($_,$i) | |
| $m = $match.Groups[$Group] | |
| } | |
| } | |
| Write-Host $_.SubString($i) | |
| } | |
| } | |
| $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Out-String',[System.Management.Automation.CommandTypes]::Cmdlet) | |
| $wrappedCmdParameters = @{} | |
| if ( $PSBoundParameters.ContainsKey("InputObject") ) { $wrappedCmdParameters.Add("InputObject",$InputObject) } | |
| $wrappedCmdParameters.Add("Stream", $True) | |
| $wrappedCmdParameters.Add("Width", $width) | |
| $scriptCmd = {& $wrappedCmd @wrappedCmdParameters | & $process_block } | |
| $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin) | |
| $steppablePipeline.Begin($PSCmdlet) | |
| } catch { | |
| throw | |
| } | |
| } | |
| Process { | |
| try { | |
| $steppablePipeline.Process($_) | |
| } catch { | |
| throw | |
| } | |
| } | |
| End { | |
| try { | |
| $steppablePipeline.End() | |
| Remove-Variable Regex | |
| } catch { | |
| throw | |
| } | |
| } | |
| } | |
| Export-ModuleMember -Function Select-MatchedString -Alias hGrep |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment