PowerShellで正規表現の使い方まとめ
正規表現は、文字列の集合を1つの文字列で表現する手法です。この記事ではPowerShellで正規表現を扱う方法を記載します。
正規表現とは
正規表現は、文字列の集合を1つの文字列で表現する手法です。1つの文字列で表現された文字列を正規表現と呼びます。正規表現は文字列のパターンマッチに使用します。
例を見た方が分かると思いますので、正規表現でできることの例を、以下に挙げます。
例えば、
- メールアドレスは
[\w\-\._]+@[\w\-\._]+\.[A-Za-z]+
- URLは
https?://[\w!\?/\+\-_~=;\.,\*&@#\$%\(\)'\[\]]+
といった1つの正規表現で表すことができます。
上記のような正規表現を用いることで、
- 「hoge@fuga.com」という文字列があった場合に、「これはメールアドレスか?」といったチェックを行う
- 「このリンク(https://hoge.fuga.com)はダミーです。」という文字列があった場合に、「この中にURLが含まれているか?」といったチェックを行う
- 「URLが含まれていたらURLを取り出す」
といった文字列のパターンマッチが可能になります。
PowerShellにおける正規表現
PowerShellで正規表現を使用する際に使用できる、コマンドレッド/ステートメント/演算子を以下に記載します。
Select-Stringを使った正規表現
Select-String
はテキストファイルから正規表現でマッチした行を検索する際に使用します。
基本的な使い方
-Path
スイッチで検索するファイルを指定し、-Pattern
スイッチで検索する正規表現を指定します。大文字/小文字は区別されません。
Select-String -Path ".\TestData\textdata.txt" -Pattern "abc"
大文字/小文字を区別する
大文字/小文字を区別する場合は、-CaseSensitive
スイッチを指定します。
Select-String -Path ".\TestData\textdata.txt" -Pattern "abc" -CaseSensitive
マッチしたかどうかをブール(TrueまたはFalse)で判定する
if文などで単に成否を判定したい場合は、-Quiet
スイッチを指定します。
$is_match = Select-String -Path ".\TestData\textdata.txt" -Pattern "abc" -Quiet
if ($is_match) {
# マッチした場合の処理
} else {
# マッチしなかった場合の処理
}
マッチした文字列を取り出す
マッチした文字列を取り出す場合は、Select-Stringが返すMatchInfo
オブジェクトから取り出すことができます。
Select-String -Path ".\TestData\textdata.txt" -Pattern "abc" | ForEach-Object { $_.Matches } | ForEach-Object { $_.Value }
Select-Stringはデフォルトでは、1行の中に複数のパターンがマッチしても先頭の1つのみを返します。マッチしたすべての文字列を取得したい場合は、-AllMatches
スイッチを指定します。
Select-String -Path ".\TestData\textdata.txt" -Pattern "abc" -AllMatches | ForEach-Object { $_.Matches } | ForEach-Object { $_.Value }
switchを使った正規表現
switch
ステートメントの-Regex
パラメータを使用すると正規表現を使って処理を切り分けできます。以下の例では指定した文字列が、Eメールアドレスか、URLかによって処理を切り分けています。
$target = 'https://hoge.fuga.com'
switch -Regex ($target)
{
'[\w\-\._]+@[\w\-\._]+\.[A-Za-z]+' { "$_ is an email address."; Break }
"https?://[\w!\?/\+\-_~=;\.,\*&@#\$%\(\)'\[\]]+" { "$_ is a URL."; Break }
}
-matchを使った正規表現
-match
演算子を使用すると正規表現を使って処理を切り分けできます。以下の例では指定した文字列が、Eメールアドレスかどうかによって処理を切り分けています。
$target = 'hoge@fuge.com'
if ($target -match '[\w\-\._]+@[\w\-\._]+\.[A-Za-z]+') {
# マッチした場合の処理
} else {
# マッチしなかった場合の処理
}
注意事項
PowerShellはデフォルトでは、大文字/小文字を区別しません。大文字/小文字を区別するには、オプションを指定する必要があります。
PowerShellで正規表現を使う際に使用するコマンドレットや演算子でオプションの指定方法が異なります。
コマンドレット/演算子 | 大文字/小文字を区別場合 |
---|---|
Select-String コマンドレット |
-CaseSensitive スイッチを付加する |
switch ステートメント |
-casesensitive オプションを付加する |
-match 演算子 |
-cmatch 演算子 |
-replace 演算子 |
-creplace 演算子 |
正規表現の構文
正規表現の構文について記載します。
正規表現の構文の説明であり、使用するコマンドレットやステートメント、演算子に依存する内容ではありませんので、以降の説明では-match
演算子を用いた例を記載します。
文字リテラル
正規表現には文字列リテラルを指定できます。正規表現に文字列リテラルを指定した場合は、指定した文字列リテラルに一致する文字にマッチします。
'foobar' -match 'ba'
文字グループ
文字グループでは指定した文字のうち、いずれかの1文字に合致します。
# 以下はword, workのいずれかにマッチする
'work' -match 'wor[dk]'
「文字グループのいずれも含まれていない」は以下のように記載します。
'worm' -match 'wor[^dk]'
文字グループにハイフン(-
)を含める場合は、後述する文字範囲
と区別するために、文字グループの先頭または末尾に-
を記載する必要があります。
'9-1=8' -match '[0-9][-+*/][0-9]'
文字範囲
文字範囲は以下のいずれかの文字の範囲を指定することができます。
'abc' -match '[a-z]bc'
'Abc' -match '[A-Z]bc'
'123' -match '[0-9]23'
# [ -~]はASCIIコードの印字可能文字(0x20~0x7E)にマッチする
'- !"#$%&()*+' -match '[ -~]'
文字クラス
10進数の数字
\d
は任意の10進の数字にマッチします。
'2020/12/31' -match '\d{4}/\d{2}/\d{2}'
単語の文字
\w
は任意の単語の文字にマッチします。[a-zA-Z_0-9]
と同義です。
'work' -match '\w{4}'
空白
\s
は空白(スペース、タブ)にマッチします。もちろんリテラルのスペースも使用できます。
' ' -match '\s\s '
ワイルドカード
.
は改行文字\n
を除く任意の1文字にマッチします。
'work' -match 'wor.'
量指定子
量指定子は直前に指定した文字が何回現れるかを指定します。PowerShellでは以下の量指定子が指定可能です。
量指定子 | 説明 |
---|---|
* |
0回以上 |
+ |
1回以上 |
? |
0回または1回 |
{n} |
ちょうどn回 |
{n,} |
n回以上 |
{n,m} |
n回以上、m回以下 |
'2020/12/31' -match '\d{4}/\d{1,2}/\d{1,2}'
アンカー
アンカーは文字の現れる場所を指定します。PowerShellでは以下のアンカーが指定可能です。
アンカー | 説明 |
---|---|
^ |
行の先頭 |
$ |
行の末尾 |
PowerShellでは$
を使用する場合、正規表現はシングルクオーテーション'
で囲う必要があります。(そうしないと変数として扱われてしまいます。)
エスケープ文字
正規表現で意味のある文字は、文字の直前にバックスラッシュ\
をつけてエスケープする必要があります。PowerShellでエスケープが必要な文字は以下の文字です。
[]().\^$|?*+{}
上記のほかに、一般的に使用されるエスケープ文字として以下の文字があります。
エスケープ文字 | 説明 |
---|---|
\t |
タブ |
\n |
改行 |
\r |
キャリッジリターン |
キャプチャとグループ
キャプチャはマッチした文字列を取得することを言います。グループはキャプチャ(または無視)する文字列を部分文字列にに分解することができます。
'An apple is the fruit.' -match '(.+is )(.+)'
-match
の正規表現でキャプチャした文字列は$Matches
自動変数に格納されます。
$Matches
# Key : 2
# Value : the fruit.
# Name : 2
#
# Key : 1
# Value : An apple is
# Name : 1
#
# Key : 0
# Value : An apple is the fruit.
# Name : 0
$Matches
は変数になっていて、$Matches[0]
にはマッチした文字列全体が格納されます。$Matches[1]
と$Matches[2]
には、グループで部分文字列に分割された文字列がキャプチャされます。
名前付きキャプチャ
キャプチャは何も指定しない場合、左からマッチした順に$Matches
自動変数にインデックス付きで格納されます。名前付きキャプチャを使うと、インデックスではなく名前を付けてキャプチャすることができます。名前を付ける場合は?<名前>
とします。
'An apple is the fruit.' -match '(?<SV>.+is )(?<O>.+)'
$Matches
の中身を確認してみましょう。Name
が変わっていることが分かると思います。
$Matches
# Key : 2
# Value : the fruit.
# Name : O
#
# Key : 1
# Value : An apple is
# Name : SV
#
# Key : 0
# Value : An apple is the fruit.
# Name : 0
名前を指定して、指定したキャプチャのみ取得することもできます。
$Matches['SV']
# An apple is
$Matches['O']
# the fruit.
置換
正規表現で置換する場合は、-replace
演算子を使って以下のように指定します。正規表現にマッチした文字列が、置換後文字列に置換されます。
<入力文字列> -replace <正規表現>, <置換後文字列>
正規表現でキャプチャした文字列を置換後文字列で使用することができます。その場合は、$1
、$2
、$3
…という自動変数に格納されます。
以下の例では、an apple
とthe fruit
をキャプチャして、入れ替えて置換しています。
'an apple is the fruit' -replace '(.+)( is )(.+)', '$3$2$1'
以下の例も、an apple
とthe fruit
をキャプチャして入れ替えて置換していますが、名前付きキャプチャを使用しています。
'an apple is the fruit' -replace '(?<S>.+)( is )(?<O>.+)', '${O} is ${S}'
最後まで読んでいただきありがとうございます。
また読んでくださいませ。
そんじゃーね。