PowerShellで文字列のパターン処理を行うときの中心が、正規表現の演算子-match(一致の判定と抽出)と-replace(置換)です。ログから特定の行を探す、日付やIDを取り出す、文字列を一括変換するといった処理が、短く書けます。
ただし、PowerShellの正規表現には他の言語と違う特徴がいくつかあります。既定で大文字小文字を区別しないこと、置換文字列はシングルクォートで囲む必要があること、パターンは正規表現なので特殊文字をエスケープすることです。これらを知らないと、思った結果になりません。この記事では、実機で確認しながら確実な書き方を解説します。
"文字列" -match "パターン"は一致すれば$trueを返し、結果を$Matchesに入れます。- 取り出しは
$Matches[0](全体)、$Matches[1](グループ)、名前付きなら$Matches["名前"]です。 - 既定で大文字小文字を区別しません。区別するには
-cmatch・-creplaceを使います。 - 置換は
"文字列" -replace "パターン", "置換後"。後方参照は$1です。 - 置換文字列はシングルクォートで囲みます。ダブルクォートだと
$1が変数展開で消えます。 - パターンは正規表現です。
.や(などの特殊文字は\.のようにエスケープします。
正規表現は、データの抽出やログ監視で多用します。条件一致したデータだけを抽出する方法、ログの特定キーワードを監視する方法、本文から特定の情報を抽出する方法とあわせて使うと効果的です。
-matchで一致するか調べる
-matchは、左の文字列が右のパターンに一致するかを$true/$falseで返します。同時に、一致した内容が自動変数$Matchesに格納されます。
# 一致すれば $true、同時に $Matches が埋まる
"order-12345" -match "\d+" # True
$Matches[0] # 12345(一致した部分全体)
# 判定だけに使うことも多い(if と組み合わせ)
if ("user@example.com" -match "@") {
Write-Host "メールアドレスっぽい"
}
# 否定は -notmatch
"abc" -notmatch "\d" # True(数字を含まない)
実機でも、"order-12345" -match "\d+"がTrueを返し、$Matches[0]が12345になりました。-matchは判定と抽出を同時に行うのが特徴です。
$Matchesでグループを取り出す
パターンの一部を丸かっこ( )で囲むと「グループ」になり、その部分を個別に取り出せます。$Matches[1]が1番目のグループ、$Matches[2]が2番目です。
if ("2026-03-09" -match "(\d{4})-(\d{2})-(\d{2})") {
$Matches[0] # 2026-03-09(全体)
$Matches[1] # 2026(年)
$Matches[2] # 03(月)
$Matches[3] # 09(日)
}
実機でも、$Matches[1]が2026、$Matches[2]が03、$Matches[3]が09になりました。番号は左のかっこから順に1, 2, 3と振られます。
名前付きグループで分かりやすく取り出す
グループが増えると番号での管理は分かりにくくなります。(?<名前>...)の形で名前を付けると、$Matches["名前"]で取り出せて読みやすくなります。
if ("2026-03-09" -match "(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})") {
$Matches["year"] # 2026
$Matches.month # 03(ドットでもアクセスできる)
$Matches["day"] # 09
}
実機で確認したところ、(?<year>...)のように名前付きグループを使うと、$Matches["year"]では取り出せる一方、$Matches[1]は空でした。名前を付けたグループは、番号ではなく名前でアクセスしてください。番号で取り出したい場合は名前を付けずに( )だけにします。
【重要】既定で大文字小文字を区別しない
PowerShellの-matchと-replaceは、既定で大文字小文字を区別しません。多くのプログラミング言語と逆なので、特に注意が必要です。区別したいときは、頭にcを付けた-cmatch・-creplaceを使います。
# 既定は大文字小文字を区別しない "ABC" -match "abc" # True(一致する) # -cmatch なら区別する(c = case-sensitive) "ABC" -cmatch "abc" # False(一致しない) # 置換も同様。-creplace で区別する "Hello HELLO" -replace "hello", "Hi" # Hi Hi(両方置換) "Hello HELLO" -creplace "hello", "Hi" # Hello HELLO(小文字のみ対象、一致なし)
実機でも、"ABC" -match "abc"はTrue、-cmatchではFalseになりました。「区別しない」のが既定だと意識しておかないと、意図せず別のものまで一致してしまいます。
-replaceで置換する(後方参照とシングルクォート)
置換は"文字列" -replace "パターン", "置換後"です。置換後の文字列で$1、$2と書くと、一致したグループを差し込めます(後方参照)。名前付きグループは${名前}で参照します。
# 単純な置換
"a1b2c3" -replace "\d", "X" # aXbXcX(数字をすべて X に)
# 後方参照で日付の並びを入れ替える
"2026-03-09" -replace "(\d{4})-(\d{2})-(\d{2})", '$3/$2/$1'
# 09/03/2026
# 名前付きグループは ${名前}
"2026-03-09" -replace "(?<y>\d{4})-(?<m>\d{2})-(?<d>\d{2})", '${y}年${m}月${d}日'
# 2026年03月09日
後方参照を使うときは、置換文字列を必ずシングルクォートで囲んでください。ダブルクォートにすると、-replaceが処理する前にPowerShellが$1を変数として展開し、空文字になってしまいます。実機でも、"$1"(ダブルクォート)では結果が空になり、'$3/$2/$1'(シングルクォート)では正しく09/03/2026になりました。なお、置換後に$そのものを出したいときは$$と書きます。
【重要】パターンは正規表現(特殊文字をエスケープ)
-replaceでつまずきやすいのが、左のパターンが正規表現として解釈されることです。.(任意の1文字)、*、(、[などは特殊な意味を持つため、文字そのものとして扱いたいときはエスケープが必要です。
# NG: . は「任意の1文字」なので全部が置換される "a.b.c" -replace ".", "-" # ----- (5文字すべて) # OK: \. でドットそのものを指定する "a.b.c" -replace "\.", "-" # a-b-c # 変数など内容が不定なら [regex]::Escape で安全にエスケープ $keyword = "a.b" $escaped = [regex]::Escape($keyword) # a\.b "xa.by" -replace $escaped, "_" # x_y
実機でも、"a.b.c" -replace ".", "-"は-----(すべて置換)、"\."にするとa-b-cになりました。利用者の入力や変数を検索文字列に使う場合は、[regex]::Escape()で特殊文字をまとめてエスケープしておくと安全です。単純な文字列置換で正規表現が不要なら、.Replace()メソッド(こちらは正規表現ではない)を使う手もあります。
配列に対する-matchはフィルタになる
-matchの左に配列を置くと、戻り値は$true/$falseではなく、パターンに一致した要素だけの配列になります。Where-Objectを使わずに絞り込めます。
$files = @("apple1", "banana", "cherry7")
# 数字を含む要素だけが返る(フィルタ)
$files -match "\d" # apple1, cherry7
# 否定で「含まないもの」を絞る
$files -notmatch "\d" # banana
# 置換も配列をまとめて処理できる
@("img1.png", "img2.png") -replace "\.png", ".webp"
# img1.webp, img2.webp
配列に対する-matchは「一致した要素を返すフィルタ」として働くため、$Matchesには一致部分が入りません。$Matchesでグループを取り出したいときは、foreachで1件ずつ-matchするか、後述の[regex]クラスを使います。実機でも、配列-match "\d"はapple1, cherry7を返しました。
Select-Stringでファイルから検索する(grep相当)
ファイルの中身を正規表現で検索するにはSelect-Stringを使います。Linuxのgrepに相当し、一致した行を行番号付きで返します。
# ファイルから "error" を含む行を探す(既定で大文字小文字を区別しない)
Select-String -Path "C:\logs\app.log" -Pattern "error"
# 複数ファイルをまとめて検索
Select-String -Path "C:\logs\*.log" -Pattern "timeout|failed"
# 結果から行番号と内容を取り出す
$hits = Select-String -Path "C:\logs\app.log" -Pattern "error"
foreach ($hit in $hits) {
Write-Host "$($hit.LineNumber): $($hit.Line)"
}
# 大文字小文字を区別するなら -CaseSensitive
Select-String -Path "C:\logs\app.log" -Pattern "ERROR" -CaseSensitive
実機でも、errorとERRORの両方が既定のSelect-Stringで一致し、行番号1と3として取得できました。Select-Stringも-matchと同じく既定で大文字小文字を区別しないため、区別したい場合は-CaseSensitiveを付けます。ログ監視と組み合わせる方法はログの特定キーワードを監視する方法で解説しています。
[regex]クラスで全件取得する
-matchは最初の一致しか$Matchesに入れません。1つの文字列の中のすべての一致を取り出したいときは、.NETの[regex]クラスを使います。
# 文字列内のすべての数値を取り出す
$all = [regex]::Matches("a1 b22 c333", "\d+")
foreach ($m in $all) {
$m.Value # 1, 22, 333 が順に取れる
}
# 値だけを配列にする
($all | ForEach-Object { $_.Value }) # 1, 22, 333
# 動的な置換(一致ごとに処理を変える)
[regex]::Replace("a1 b2", "\d", { param($m) [int]$m.Value * 10 })
# a10 b20
実機でも、[regex]::Matches("a1 b22 c333", "\d+")は1, 22, 333をすべて返しました。[regex]::Replace()にスクリプトブロックを渡すと、一致ごとに計算して置換するような高度な処理もできます。
よくある失敗
大文字小文字が区別されると思い込む
-match・-replace・Select-Stringはいずれも既定で区別しません。区別したいなら-cmatch・-creplace・-CaseSensitiveを使います。
置換文字列をダブルクォートで囲んでが消える
ダブルクォートだとPowerShellが$1を変数展開します。後方参照を使う置換文字列は、必ずシングルクォートで囲んでください。
パターンの特殊文字をエスケープし忘れる
.や(などは正規表現の特殊文字です。文字そのものを指定するなら\.のようにエスケープするか、[regex]::Escape()を使います。
名前付きグループを番号で取り出そうとする
名前を付けたグループは$Matches["名前"]で取り出します。$Matches[1]では取れません。番号で取りたいなら名前を付けません。
配列の-matchで$Matchesを見て混乱する
配列に対する-matchはフィルタで、$Matchesは埋まりません。グループを取り出すなら1件ずつ処理するか[regex]クラスを使います。
よくある質問
-matchを-cmatch、-replaceを-creplace、Select-Stringに-CaseSensitiveを使ってください。-replaceが処理する前にPowerShellが$1などを変数として展開し、空文字になってしまうためです。後方参照を使うときはシングルクォートで囲み、$1をそのまま-replaceへ渡します。-matchは最初の1件だけです。すべての一致は[regex]::Matches(文字列, パターン)で取得し、各要素の.Valueで値を取り出します。Select-String -Path ファイル -Pattern パターンを使います。一致した行を行番号付きで返し、Linuxのgrepのように使えます。複数ファイルやワイルドカードにも対応します。.Replace("古い", "新しい")メソッドが使えます。これは正規表現ではないため、.などもそのままの文字として扱われます。まとめ
-matchは一致判定と抽出を同時に行い、結果は$Matchesに入ります。- グループは
$Matches[1]、名前付きは$Matches["名前"]で取り出します。 - 既定で大文字小文字を区別しません。区別するなら
-cmatch・-creplaceです。 -replaceの後方参照は$1。置換文字列はシングルクォートで囲みます。- パターンは正規表現なので、特殊文字は
\.や[regex]::Escape()でエスケープします。 - ファイル検索は
Select-String、全件取得は[regex]::Matchesを使います。
PowerShellの正規表現は、「大文字小文字を区別しない」「置換文字列はシングルクォート」「パターンは正規表現」という3つの特徴さえ押さえれば、検索も置換も思いどおりに書けます。ログ解析やデータ抽出のスクリプトが、ぐっと短く正確になります。

