開発ブログ

WWWクリエイターズが送る、Git、CSS、HTML、コマンドライン、Macの便利機能など、開発に関する役立ち情報発信します。気まぐれに更新。

正規表現:改行を越えて複数行にまたがるマッチング方法

最終更新:2017-11-06 by Joe

正規表現において、通常、特殊文字「.」は「改行を除くすべての文字」を表現します。

頻繁に利用する「.」ですが、改行を越えてすべての文字を吟味できません。改行を含めて文字列マッチを見つける方法をまとめました。

複数行を検索する表現

特殊文字「.(改行以外の1文字)」と量指定子の「*(0回以上の連続)」などを利用して、任意の文字列をマッチさせる正規表現「.*」はよく利用します。注意が必要なのは、文字列中に「改行」があるとそこで途切れてしまうという点です。

「改行を含めたすべての文字列」を対象としたい時は、下記の2つのエスケープシーケンス表現を利用します。

  • \s :空白、タブ、フォーム フィードなどの任意の空白文字
  • \S:空白文字以外の任意の文字

これらは、互いに反対の関係です。PHPでの使用例を見てみます。

改行をこえて、複数行をマッチさせる(PHP)

$subject = "
The text you
need to search.
";

// 改行コードを含むべての文字列
if ( preg_match( '/[\s\S]*/', $subject ) )
  echo "Matched";

[]の角括弧による表現は、「文字セット」や「文字クラス」と呼ばれ、カッコ内にふくまれるすべての文字を対象とします。

上記の例は、\sか、\Sのいずれかの文字、すなわち「空白を含むすべての文字」で、0回以上繰り返す、最長のマッチを探す事になります。

シングルラインモードとマルチラインモードについて

改行の取り扱いに関して、プログラミング言語によっては、シングルラインモード、マルチラインモードという2つのモードを切り替えられます。たとえば、PHPやperlでは、修飾子「m」と「s」で、それらのモードを区別します。シングルラインモードでは、「.」の意味が変化し「改行を含む」ように動作します。)

PHPドキュメントより抜粋

修飾子意味
m (PCRE_MULTILINE)デフォルトで、PCRE は、検索対象文字列を(実際には複数行からなる 場合でも)単一の行からなるとして処理します。 「行頭」メタ文字 (^) は、対象文字列の最初にしかマッチしません。 一方、「行末」メタ文字 ($) は、文字列の最後、または (D 修飾子が設定されていない場合) 最後にある改行記号の前のみにしかマッチしません。 この動作は Perl と同じです。 この修飾子を設定すると、「行頭」および「行末」メタ文字は 対象文字列において、文字列の最初と最後に加えて、 各改行の直前と直後にそれぞれマッチします。 この動作は、Perl の /m 修飾子と同じです。 対象文字列の中に "\n" 文字がない場合や、 またはパターンに ^ または $ がない場合は、 この修飾子を設定しても意味はありません。
s (PCRE_DOTALL)この修飾子を設定すると、パターン中のドットメタ文字は 改行を含む全ての文字にマッチします。 これを設定しない場合は、改行にはマッチしません。 この修飾子は、Perl の /s 修飾子と同じです。 [^a] のような否定の文字クラスは、 この修飾子の設定によらず、常に改行文字にマッチします。

つまりPHPでは下記のような表現が可能です。

$subject = "
The text you
need to search.";

// 改行コードを含むべての文字列
if ( preg_match( '/.*/s', $subject ) )
  echo "Matched";

モードの切り替えによって「.」の意味だけでなく「^」の意味が混乱しやすいので、注意が必要です。不要な混乱をさけるため、筆者はあまり積極的にはシングルラインモードを使いません。

参考

閉じる