Windows PowerShell
正規表現の実例
Don Jones
以前にも、Windows PowerShell の正規表現についてのコラムを書いたことがありましたが、多くの場合は、正規表現の機能や使用法の観点から解説していました。今月は、Windows PowerShell の正規表現の実用的な使用例に重点を置いて解説をします。この使用例は、私が作成したカスタマー ソリューションに基づいているので、正規表現の威力を示す好例です。 一般的な問題たとえば、次のような問題が起こります。Windows PowerShell を使用して、Web ページからテキストを取得する必要があります。Web ページは、Web ブラウザーでページがどのように表示されるかを指定する HTML に基づいた、単純なテキスト ドキュメントとして転送されることに留意します。そのテキストから、すべてのハイパーリンクを抽出して一覧形式で表示し、ローカルのテキスト ファイルに出力するか、その他の方法で保存する必要があります。HTML では、ハイパーリンクは <a> タグで示され、<a href=" http://concentratedtech.com">ここをクリック</a> のように示されます。 難しいのは、<a> タグでは、リンクを新しいページで開くようにする target など、数多くのオプション パラメーターがサポートされている点です。<a> タグには、href パラメーターの代わりに、ページ内のアンカーを設定する name パラメーターが含まれる場合があります。ですが、ここでは、このような <a> タグの情報は取得せず、他のページに飛ぶ、正真正銘のアウトバウンド リンクのみを取得する必要があります。 |
このコラムでは、今後も Windows PowerShell 1.0 で使用できる機能と技法について取り上げますが、徐々に Windows PowerShell 2.0 特有の機能にシフトする予定です。Windows PowerShell 2.0 は、Windows 7 と Windows Server 2008 R2 に同梱されプレインストールされています。このコラムが公開されるころには、Windows Vista、Windows Server 2008、Windows XP、および Windows Server 2003 でも Windows PowerShell 2.0 が使用できるようになる予定です。このバージョンが利用できるようになったかどうかを確認して、ダウンロードするには、microsoft.com/PowerShell (英語) にアクセスしてください。 |
一般的に直面する難題
正規表現を扱うのは、パズルを解くこととよく似ています。3D ポスターを見ているときのように、目を細めながら手掛かりを探しているのではないでしょうか。情報は、文字単位ではなく、パターン形式で見る必要があります。目を細めると文字がぼやけるので、大きなパターンに集中できます。次の 4 つのハイパーリンクを見てください。
<a href="http://concentratedtech.com">ここをクリック</a>
<a name="data">データ シート</a>
<a target="_blank" href="https://microsoft.com/japan">マイクロソフト</a>
<a href="search.aspx" target="_top">検索</a>
次の共通の要素が含まれているハイパーリンクを取得する必要があります。
- <a で始まる
- </a> で終わる
- <a と > の間のどこかに href=" がある
この要素をすべて含んでいないハイパーリンクは取得しません。関係のない部分を無視して、目を細めると、ハイパーリンクは次のように見えます。
<a_href=”xxxxxxxxx">xxxxxxx</a>
<a_xxxxxxxx>xxxxxxx</a>
<a_xxxxxxxxxx_href="xxxxxxxxx">xxxxxxxx</a>
<a_href="xxxxxxxxx"_xxxxxxxxxx>xxxxxxxx</a>
空白文字をアンダースコアで置き換えて少し目立つようにして、関係のない部分を x で置き換えたことに着目してください。これらのリンクは、突如似ているように見え始め、パターンが現れます。
正規表現のパターン
パターンは、正規表現で一番大切なものです。正規表現固有の表記を使用して、検索するテキストのパターンを表現します。Windows PowerShell で Help about_regular_expressions というコマンドを実行すると、正規表現言語についての総合的な概要情報を参照できます。
今回、正規表現のパターンは次のようになります。
(<a\s.{0,}?href=".+?".{0,}?>.+?</a>)
確かに、これではわけがわかりません。私も、RegExTester.com の Web サイト (英語) を何度も参照して、この正規表現を作成するのに 1 時間ほどかかりました。では、この正規表現について詳しく説明しましょう。
- かっこで囲まれている部分は、1 つのハイパーリンクのパターンを定義して、Windows PowerShell に一致項目を取得するように指示しています (一致項目の取得については、後ほど詳しく説明します)。
- <a はリテラル文字列で、Windows PowerShell では、その 2 文字を探します。
- \s は、1 個の空白文字を表します。この空白文字は、HTML において必ず <a の後に必ずある空白文字に一致します。
- .{0,}? では、種類にかかわらず、0 個以上の文字があることを指定しています。ピリオドは "すべての文字" を意味し、{0,} は 0 個以上を意味しています。その後にある疑問符には特殊な意味があり、これにより、項目を最短一致 (後ほど詳しく説明します) で探すようになります。
- 次に、href=" というリテラル文字を探します。
- そして、1 個以上の文字を探します。プラス記号は "1 個以上" を意味します。その後にある疑問符によって、再度最短一致が使用されます。
- それから、終了の引用符を探します。
- 次に、0 個以上の文字と終了の > を探します。
- 最後に、</a> の前にある 1 個以上の文字を探します。ここでも、プラス記号の後にある疑問符により、最短一致が使用されます。
この最短一致は、扱うのが難しい手法です。たとえば、HTML ページに次のようなテキスト文字列があるとします。
これは<a href="test">リンク</a>で、これも<a href="test">リンク</a>ですが、これはリンクではありません。
そして、このテキスト文字列に対して、項目を探すのに最短一致を適用する疑問符を含まない次の正規表現を使用するとします。
(<a\s.{0,}href=".+".{0,}>.+</a>)
Windows PowerShell では、最初の <a と空白文字が一致する項目を検索して、それから 0 個以上の文字を探しますが、最後の </a> を見つけない限り、この検索処理を終了しません。次に、一致した項目を太字で示します。
これは**<a href="test">リンク</a>で、これも<a href="test">リンク</a>**ですが、これはリンクではありません。
このような結果になるのは、最初の .{0,} で項目を最長一致で探しているからです。Windows PowerShell では、正規表現が機能するようにするのと同時に、できるだけ多くの文字を取得します。最短一致を使用することで、Windows PowerShell では、正規表現を機能するようにするのと同時に、次のようにできるだけ少ない文字を取得するようになります。
これは**<a href="test">リンク</a>で、これも<a href="test">リンク</a>**ですが、これはリンクではありません。
一般的なソリューション
Windows PowerShell でこの正規表現が機能するように、まずテスト用の変数を定義して、HTML を格納しました。次に -match 演算子を使用して、正規表現と一致する項目がテスト用の HTML にあるかどうかを確認しました。
PS C:\> $html = 'これは<a href="test">テスト</a>ですが<a name="anchor">これ</a> はテストではなく<a target="_top" href="something">確かに</a>リンクです。'
PS C:\> $html -match '(<a\s.{0,}?href=".+?".{0,}?>.+?</a>)'
True
True という結果から、1 つ以上の一致項目が見つかったということはわかりますが、どの項目が一致したのかについてはわかりません。ですが、-match 演算子を使用すると、自動的に $matches という名前の配列が作成されます。この配列には、取得された一致項目すべてが含まれています。
PS C:\> $matches
名前 | 値 |
1 | <a href="test">テスト</a> |
0 | <a href="test">テスト</a> |
次に示す通常の配列の構文を使用すると、個々の一致項目にアクセスできます。
PS C:\> $matches[0]
<a href="test">テスト</a>
また、次のコマンドを実行すると、配列の内容をファイルにも簡単に出力できます。
PS C:\> $matches | out-file c:\matches.txt
構文を完全に習得したら、奇妙なものであることに変わりはありませんが、強力で有益な方法を使用して、膨大な量のテキストから複雑な可変パターンに一致する項目を検出できます。また、パターンに一致するテキストを抽出して、テキストの本文とは別の場所で使用することができます。これは、ログ ファイル、HTML ファイルなど、半構造化された種類のテキストを解析する際に特に便利です。
Don Jones は、TechNet Magazine の編集に携わっており、www.ConcentratedTech.com (英語) で Windows PowerShell に関するヒントとニュースを公開しています。また、『Windows PowerShell 2.0: TFM』(Sapien Press、2009 年) の共著者でもあります。同書の第 3 版では、Windows PowerShell 2.0 について扱っています。