PowerShell はオブジェクトを扱えるので、Grep のように正規表現マッチで String の検索を行うことは多くないものの、たまーーにコンソール出力内容の検索したくなることがあり、ハイライトしてくれればいいのにとずっと思っていたので方法をメモ。
環境は PowerShell Core 6.2。
結果から
Before
After
Yay!
参考にしたスクリプト
以下の 2 つのスクリプトを参考にしました。多謝。
Get-ChildItem や Select-String の表示形式を変更するモジュール。ただし。正規表現マッチ部をハイライトする機能はない。
タイトル通り、PowerShell の既定出力である Out-Default をフックするサンプル。
Profile.ps1
以下のコードを Profile.ps1 に書けば実現できます。
function MatchInfo {
param (
[Parameter(Mandatory = $True, Position = 1)]
$match
)
# 色の設定
$PSColor = @{
Default = 'White'
Path = 'Cyan'
LineNumber = 'Yellow'
Line = 'White'
MatchedText = 'Red'
BackGround = 'White'
}
# 行数表示
Write-host $match.LineNumber -foregroundcolor $PSColor.LineNumber -noNewLine
Write-host ":`t" -foregroundcolor $PSColor.Default -noNewLine
# 該当行をマッチしたテキストで Split し、色を変えて出力
$ParsedText = $match.Line -split $match.pattern
Write-host $ParsedText[0] -foregroundcolor $PSColor.Line -noNewLine
for ($i = 1; $i -lt $ParsedText.length; $i += 1) {
Write-host $match.matches[0].value -foregroundcolor $PSColor.MatchedText -noNewLine
Write-host $ParsedText[$i] -foregroundcolor $PSColor.Line -noNewLine
}
Write-Host
}
function Out-Default {
[CmdletBinding(ConfirmImpact = "Medium")]
param
(
[Parameter(ValueFromPipeline = $true)]
[System.Management.Automation.PSObject] $InputObject
)
begin {
$wrappedCmdlet = $ExecutionContext.InvokeCommand.GetCmdlet("Out-Default")
$sb = { & $wrappedCmdlet @PSBoundParameters }
$__sp = $sb.GetSteppablePipeline()
$__sp.Begin($pscmdlet)
}
process {
# 受け取ったオブジェクトが MatchInfo だった場合
if ($_ -is [Microsoft.Powershell.Commands.MatchInfo]) {
MatchInfo $_
}
# MatchInfo 以外ならパイプライン処理を続ける
elseif (![string]::IsNullOrEmpty($_)) {
$__sp.Process($_)
}
}
end {
$__sp.End()
}
}