【PowerShell】正規表現を使って文字列の一部を抽出する方法

2019年8月19日

たとえば、URLのあるスラッシュから次のスラッシュまでの文字列を抜き出したいなー

と思ったときに、URLにはスラッシュがたくさんあるからうまくスラッシュとスラッシュの間の文字を抜き出せない!!

なんてことになって途方に暮れたことありますよね⇐僕の体験談

そんな時は正規表現を使いこなして目的を達成しよう!

例えば、こんな文字列があったとします。

aaa/bbb/ccc/任意の文字列/eee/fff/ggg.html

ここから

aaa/bbb/ccc/任意の文字列/

を抜き出したいとします。

そんな時はPowerShellだとこんな風に書けます。

"aaa/bbb/ccc/任意の文字列/eee/fff/ggg.html" -match ".*/ccc/.*?/"

これを実行すると以下のようになります!

PS C:\> "aaa/bbb/ccc/任意の文字列/eee/fff/ggg.html" -match ".*/ccc/.*?/"
True
PS C:\> $Matches
Name                           Value
----                           -----
0                              aaa/bbb/ccc/任意の文字列/

目的とする「aaa/bbb/ccc/任意の文字列/」が取れました。

ちなみに、-matchの結果は勝手に$Matchesに格納されるようになっています。

さて、解説します。

コードで出てきた「.*」は何を表しているかというと、

「.」は「 任意の1文字 」

「*」は「直前の文字の0回以上の繰り返し 」

この二つを組み合わせると、任意の1文字の0回以上の繰り返しとなり、「/ccc」より前の部分が全て取得できて、「 aaa/bbb 」が取得されてきます。

そしてもう一つ、これが今回の「次のスラッシュまで」を取得するのにとても重要となります。

「.*?」はどういうことかというと、

「.」は先ほどと同様で、「 任意の1文字 」

「*?」 は「 直前の文字の0回以上の繰り返し 」

この二つを組み合わせると、任意の1文字の0回以上の繰り返しとなり 、、、

え????

「.*」と 「*?」 って同じじゃん!!

と思ったかと思いますが、違うものなんです!

この違いが重要!!

「*」と「*?」の大きな違いは、 「 最長一致 」か「 最短一致 」かということです。

「*」 が 「 最長一致 」

「*?」が 「 最短一致 」

最長一致とは、条件に合う一番長い部分に一致します。

最短一致とは、条件に合う一番短い部分に一致します。

どういうことかというと、例えば今回の場合、

PS C:\> "aaa/bbb/ccc/任意の文字列/eee/fff/ggg.html" -match ".*/ccc/.*?/"
True
PS C:\> $Matches
Name                           Value
----                           -----
0                              aaa/bbb/ccc/任意の文字列/
 
PS C:\> "aaa/bbb/ccc/任意の文字列/eee/fff/ggg.html" -match ".*/ccc/.*/"
True
PS C:\> $Matches
Name                           Value
----                           -----
0                              aaa/bbb/ccc/任意の文字列/eee/fff/

「.*?」を使った場合は、「aaa/bbb/ccc/任意の文字列/」が取れて、

「.*」 を使った場合は、 「aaa/bbb/ccc/任意の文字列/eee/fff/」

「.*?」 は一番近くにある次の「/」までを取得して、

「.*」は一番遠くにある(一番右側)にある 「/」までを取得する。

それが、「 最長一致 」と「 最短一致 」の大きな違いなんです。

この違いをしっかり意識して正規表現を学んでいきましょう!

スポンサーリンク

PowerShell

Posted by ton