̃Gg[͂ĂȃubN}[Nɒlj

PHP :: 正規表現 / パターン修飾子「m」「s」



m (PCRE_MULTILINE)

  • 複数行として扱う

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

s (PCRE_DOTALL)

  • . (ドット)を改行文字にもマッチさせる

この修飾子を設定すると、パターン中のドットメタ文字は 改行を含む全ての文字にマッチします。
これを設定しない場合は、改行にはマッチしません。
この修飾子は、Perl の /s 修飾子と同じです。[^a] のような否定の文字クラスは、この修飾子の設定によらず、常に改行文字にマッチします。
(PHPマニュアルより引用)

以下、サンプルコード

<?php
 
$str = 'abc
axz
ayz';
 
// パターン修飾子「なし」
preg_match_all('/^a.*z$/', $str, $cap);
var_dump($cap);
array(1) {
  [0]=>
  array(0) {
  }
}
 
// パターン修飾子「m」
preg_match_all('/^a.*z$/m', $str, $cap);
var_dump($cap);
array(1) {
  [0]=>
  array(1) {
    [0]=>
    string(3) "ayz"
  }
}
 
// パターン修飾子「s」
preg_match_all('/^a.*z$/s', $str, $cap);
var_dump($cap);
array(1) {
  [0]=>
  array(1) {
    [0]=>
    string(13) "abc
axz
ayz"
  }
}
 
// パターン修飾子「ms」
preg_match_all('/^a.*z$/ms', $str, $cap);
var_dump($cap);
array(1) {
  [0]=>
  array(1) {
    [0]=>
    string(13) "abc
axz
ayz"
  }
}
 
?>



では、以下の結果を得たい時はどうするか?

array(1) {
  [0]=>
  array(2) {
    [0]=>
    string(4) "axz
"
    [1]=>
    string(3) "ayz"
  }
}

答え

preg_match_all('/^a.*z\r?\n?$/m', $str, $cap);
var_dump($cap);

/m オプションで、$の直前に改行をあらわすエスケープシーケンスを追加する。
※. Windows で検証した為、改行は「\r\n」になっています。



エスケープシーケンス「$」を外した場合

// パターン修飾子「なし」
preg_match_all('/^a.*z/', $str, $cap);
var_dump($cap);
array(1) {
  [0]=>
  array(0) {
  }
}
 
// パターン修飾子「m」
preg_match_all('/^a.*z/m', $str, $cap);
var_dump($cap);
array(1) {
  [0]=>
  array(2) {
    [0]=>
    string(3) "axz"
    [1]=>
    string(3) "ayz"
  }
}
 
// パターン修飾子「s」
preg_match_all('/^a.*z/s', $str, $cap);
var_dump($cap);
array(1) {
  [0]=>
  array(1) {
    [0]=>
    string(13) "abc
axz
ayz"
  }
}
 
// パターン修飾子「ms」
preg_match_all('/^a.*z/ms', $str, $cap);
var_dump($cap);
array(1) {
  [0]=>
  array(1) {
    [0]=>
    string(13) "abc
axz
ayz"
  }
}



さらに、エスケープシーケンス「^」も外した場合(^$を両方とも外す)

// パターン修飾子「なし」
preg_match_all('/a.*z/', $str, $cap);
var_dump($cap);
array(1) {
  [0]=>
  array(2) {
    [0]=>
    string(3) "axz"
    [1]=>
    string(3) "ayz"
  }
}
 
// パターン修飾子「m」
preg_match_all('/a.*z/m', $str, $cap);
var_dump($cap);
array(1) {
  [0]=>
  array(2) {
    [0]=>
    string(3) "axz"
    [1]=>
    string(3) "ayz"
  }
}
 
// パターン修飾子「s」
preg_match_all('/a.*z/s', $str, $cap);
var_dump($cap);
array(1) {
  [0]=>
  array(1) {
    [0]=>
    string(13) "abc
axz
ayz"
  }
}
 
// パターン修飾子「ms」
preg_match_all('/a.*z/ms', $str, $cap);
var_dump($cap);
array(1) {
  [0]=>
  array(1) {
    [0]=>
    string(13) "abc
axz
ayz"
  }
}



programming/php/regex/pattern_qualification_ms.txt