2020/05/03 更新
ANSI エスケープシークエンスを使う方法 でもっとシンプルに実装できました。
作ったもの
コンソールエミュレータは Cmder が好きです。
環境
PS > $PSVersionTable
Name Value
---- -----
PSVersion 5.1.18362.145
PSEdition Desktop
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}
BuildVersion 10.0.18362.145
CLRVersion 4.0.30319.42000
WSManStackVersion 3.0
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
コード
function Write-StringHighlight {
<#
.SYNOPSIS
文字列内の指定箇所を強調表示する
・パイプライン経由での入力にのみ対応
.PARAMETER pattern
検索パターン
.PARAMETER case
指定時は大文字小文字を区別
.PARAMETER color
強調箇所の色
.PARAMETER plainColor
強調しない箇所の色
.PARAMETER continuous
指定時は出力後に改行しない
#>
param (
[string]$pattern = ".",
[switch]$case,
[ValidateSet("White", "Black", "Blue", "DarkBlue", "Green", "DarkGreen", "Cyan", "DarkCyan", "Red", "DarkRed", "Magenta", "DarkMagenta", "Yellow", "DarkYellow", "Gray", "DarkGray")][string]$color = "Yellow",
[ValidateSet("White", "Black", "Blue", "DarkBlue", "Green", "DarkGreen", "Cyan", "DarkCyan", "Red", "DarkRed", "Magenta", "DarkMagenta", "Yellow", "DarkYellow", "Gray", "DarkGray")][string]$plainColor = "Gray",
[switch]$continuous
)
$capture = "(?<pre>.*?)(?<main>{0})(?<post>.*)" -f $pattern
if ($case) {
$r = [regex]$capture
}
else {
$r = [regex]"(?i)$capture"
}
$loopFlag = $true
if ($pattern.Substring(0,1) -eq "^") {
$loopFlag = $false
}
foreach ($i in $input) {
Do {
if (-not $r.IsMatch($i)) {
break
}
$m = $r.Matches($i)
Write-Host $m[0].Groups["pre"].Value -ForegroundColor $plainColor -NoNewline
Write-Host $m[0].Groups["main"].Value -ForegroundColor Black -BackgroundColor $color -NoNewline
$i = $m[0].Groups["post"].Value
} while ($loopFlag)
Write-Host $i -ForegroundColor $plainColor -NoNewline:$continuous
}
}
# Alias
Set-Alias "hilight" Write-StringHighLight
個人的には $profile
に書いておいて各種コマンドレット内で使いまわしています。
仕組み
自動変数 $input
でパイプラインからの入力を受け取って各要素を処理しています。
アルゴリズムというほどでもありませんが、正規表現の名前付きキャプチャ(参考記事)で文字列をマッチ箇所とその前後に分割し、ループを繰り返しながら後方へとマッチ箇所を探索します。事前に ^
の有無を判定しているのはループのたびに先頭部分にマッチしてしまうからです。
Write-Host
による出力ですので、パイプ処理の途中でのフィルタ的な使い方はできません。あくまで検索結果を視覚的に確認するために作成したコマンドレットです。
エイリアスの hilight は 秀丸エディタ の設定リスペクトです。