【2023年】これからブログを始める人へおすすめの書籍

Kissy

PowerShellで正規表現の使い方まとめ

作成: 更新:

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 applethe fruitをキャプチャして、入れ替えて置換しています。

'an apple is the fruit' -replace '(.+)( is )(.+)', '$3$2$1'

以下の例も、an applethe fruitをキャプチャして入れ替えて置換していますが、名前付きキャプチャを使用しています。

'an apple is the fruit' -replace '(?<S>.+)( is )(?<O>.+)', '${O} is ${S}'

最後まで読んでいただきありがとうございます。
また読んでくださいませ。
そんじゃーね。

関連記事

SPONSORED LINK
SPONSORED LINK