"line break" is ill-defined:
-- Windows uses CR+LF (\r\n)
-- Linux LF (\n)
-- OSX CR (\r)
Little-known special character:
\R in preg_* matches all three.
preg_match( '/^\R$/', "match\nany\\n\rline\r\nending\r" ); // match any line endings
バックスラッシュ〔日本語環境では円記号となる場合もある〕には、 いくつかの使用法があります。ひとつめの使用法は、 非英数字の前に記述する場合で、続く文字が表す特別な意味を取り去ります。 このエスケープ文字としての使用法は、 文字クラスの内外部いずれでも可能です。
たとえば、"*" 文字とマッチさせたい場合は、パターンを "\*" と記述します。 続く文字がメタ文字として解釈されるものであるかには関係ありませんので、 いかなる非英数字に対しても、"\" を付けると、その文字自体が 表わされることになります。特に、 バックスラッシュとマッチさせたい場合は、"\\" と記述します。
注意:
シングルクォートあるいはダブルクォートで囲まれた PHP の 文字列 の中では、バックスラッシュは特別な意味を表します。 そのため、正規表現 \\ を使用して \ とマッチさせたい場合は PHP のコード内では "\\\\" あるいは '\\\\' と記述する必要があります。
パターンを、 PCRE_EXTENDED オプションを付けてコンパイルすると、(文字クラス内部を除き) パターン中の空白文字、および "#" とその次の改行文字との間の文字は 無視されます。空白文字や "#" をパターン中に含めるには、 バックスラッシュを用いてエスケープします。
バックスラッシュの 2 番目の使用法は、非表示文字〔制御コードなど〕を パターン中に目に見える形で記述するための方法です。ヌル文字は パターンを終了させてしまうため使えませんが、その他の非表示文字は、 パターンにそのまま含めても問題はありません。しかし、パターンの編集には、 バイナリ文字をそのまま用いるよりも、以下に示すエスケープシーケンスを 用いる方が便利でしょう。
"\cx
" の正確な働きは、次の通りです。
"x
" が小文字の場合、
大文字に変換されます。続いて、文字の 6 ビット目 (16進数 40) が
反転されます。つまり、"\cz
" は 16 進数の 1A になり、
"\c{
" は 3B になり、
"\c;
" は 7B になります。
"\x
" の後では、2 桁までの 16 進数が読まれます
(大小文字どちらも可能です)。
UTF-8 モード では、
"\x{...}
" という記法も使えます。
この場合、波括弧の中身は16進数を示す文字列です。
この文字列は、16進数の数値でコードポイントを表す UTF-8 文字として解釈されます。
オリジナルの16進のエスケープシーケンス \xhh
は、
値が127より大きい場合、2バイトのUTF-8 文字とマッチします。
"\0" の後では、さらに 2 桁の 8 進数が
読みこまれます。いずれの場合も、2 桁より少ない場合、桁があるだけ
読みこまれます。つまり、"\0\x\07
" は
ヌル文字 2 つの後にベル文字が
続いたものを表します。8 進数を指定する場合は、必ず最初のゼロに続いて
残りの 2 桁の数字を指定するように注意してください。
バックスラッシュの後に 0 以外の数字が続く場合の処理は複雑です。 文字クラスの外部では、 PCRE は、続く数字全体を 10 進数として読みます。 数字が 10 よりも小さい場合、または、正規表現の中に含まれる キャプチャ用左カッコの数以下の場合、 後方参照 として解釈されます。 この動作に関する詳しい説明は、後ほど、カッコによるサブパターンの説明を 行ってから示します
文字クラスの中、または、指定された 10 進数が 9 より大きく、 キャプチャ用サブパターンの数がこの数に満たない場合は、PCRE は バックスラッシュの後から最大 3 文字の 8 進数を再度読みこみ、 その値の最下位 8 ビットから 1 バイトを生成します。 その後に続く数字は、それ自体を表します。以下に例を示します。
3 桁を超えて 8 進数は読みこまれないため、100 以上の 8 進数には ゼロを前につけてはいけないことに注意してください。
これらの 1 バイト値を定義するエスケープシーケンスは、
文字クラスの内外部のいずれでも使用できます。加えて、文字クラス内では
エスケープシーケンス "\b
" はバックスペース (16進 08) として解釈されます。
文字クラス外では、別の意味を有します(別記参照)。
バックスラッシュの第 3 の使用法は、包括的な文字型を指定する用途です。
これらエスケープシーケンスの各組により、文字集合が 2 つに分割されます。 文字は、各組のどちらか片方だけにマッチします。
空白文字とは HT (9)、LF (10)、FF (12)、CR (13)、スペース (32) のことです。 しかし、ロケールを指定したマッチングを行った場合には、 128から255までのコードポイントの文字 (たとえば NBSP (A0)) も空白文字とみなされる可能性があります。
単語構成文字とは、英字または数字またはアンダースコア文字であり、Perl
が定義するところの「単語」と成り得る文字のことです。文字および数字の
定義は、PCRE の文字テーブルにより制御され、ロケールを指定して
マッチングを行うと変わる可能性があります。
例えば、"fr" (フランス語)ロケールの場合、128 を超える
文字コードのいくつかは、アクセント付きの文字に使われており、
これらは \w
とマッチします。
これらの文字型表記は、文字クラスの内外によらず使用可能で、 対応する型のたかだか 1 文字とマッチします。現在のマッチング位置が 検索対象文字列の終端である場合、マッチできる文字が無いので、 マッチは失敗します。
バックスラッシュの第 4 の使用法は、簡単な言明 (assertion) です。 言明とは、マッチがある特定の位置でだけ可能だという条件を指定するもので、 検索対象文字列から文字を消費 (consume)〔つまり文字自体にマッチ〕 しません。サブパターンを使ったより複雑な言明の方法もありますが、 それについての解説は後ほど行います。バックスラッシュを使った言明は、 次のものがあります
これらの言明は、文字クラス内では使用できません(また、文字クラス内では、
"\b
" はバックスペース文字という別の意味を持つので
注意してください)。
単語境界 (word boundary) とは、検索対象文字列において、
カレントの文字およびその前の文字が同時に \w
もしくは \W
にマッチしない(すなわち、片方が
\w
にマッチし、もう片方が \W
にマッチする)位置、もしくは、文字列の始めか終わりで、
その始めか終わりの文字が \w
にマッチする位置の
ことです。
言明 \A
, \Z
,
\z
は、(アンカー で説明する)ハット記号やドル記号とは
異なり、オプション設定によらず、文字列の始端または終端だけに
マッチします。これらの言明は、PCRE_MULTILINE および PCRE_DOLLAR_ENDONLY
オプションの影響を受けません。
\Z
と \z
との違いは、
\Z
は文字列の末尾の改行の前の位置および文字列の
終端にマッチするのに対し、\z
は文字列の終端にのみ
マッチすることです。
言明 \G
は、カレントのマッチング位置が、
preg_match() 関数の offset
引数に指定されたマッチングの開始位置である場合に真になります。
offset
が非ゼロの場合は、\A
と等価ではありません。
\Q
と \E
とを使って、
パターン中のメタ文字を無視させることができます。
たとえば、
\w+\Q.$.\E$
は、文字列の終端において1つ以上の単語構成文字のあとに .$.
というリテラルが続いたものにマッチします。
これらは、デリミタの動作を変更しないことに注意して下さい。
たとえば、#\Q#\E#$
は無効なパターンです。
なぜなら、#
がパターンの終端としてマークされ、
\E#
が無効な修正子と解釈されるからです。
\K
を使用すると、マッチの開始位置をリセットできます。
たとえば、パターン
foo\Kbar
は "foobar" にマッチしますが、
結果は "bar" にマッチしたと報告されます。
\K
を使用しても、キャプチャした部分文字列には影響を及ぼしません。
たとえば、パターン (foo)\Kbar
が
"foobar" にマッチしたときの最初の部分文字列は "foo" です。
"line break" is ill-defined:
-- Windows uses CR+LF (\r\n)
-- Linux LF (\n)
-- OSX CR (\r)
Little-known special character:
\R in preg_* matches all three.
preg_match( '/^\R$/', "match\nany\\n\rline\r\nending\r" ); // match any line endings
Significantly updated version (with new $pat4 utilising \R properly, its results and comments):
Note that there are (sometimes difficult to grasp at first glance) nuances of meaning and application of escape sequences like \r, \R and \v - none of them is perfect in all situations, but they are quite useful nevertheless. Some official PCRE control options and their changes come in handy too - unfortunately neither (*ANYCRLF), (*ANY) nor (*CRLF) is documented here on php.net at the moment (although they seem to be available for over 10 years and 5 months now), but they are described on Wikipedia ("Newline/linebreak options" at https://en.wikipedia.org/wiki/Perl_Compatible_Regular_Expressions) and official PCRE library site ("Newline convention" at http://www.pcre.org/original/doc/html/pcresyntax.html#SEC17) pretty well. The functionality of \R appears somehow disappointing (with default configuration of compile time option) according to php.net as well as official description ("Newline sequences" at https://www.pcre.org/original/doc/html/pcrepattern.html#newlineseq) when used improperly.
A hint for those of you who are trying to fight off (or work around at least) the problem of matching a pattern correctly at the end ($) of any line in multiple lines mode (/m).
<?php
// Various OS-es have various end line (a.k.a line break) chars:
// - Windows uses CR+LF (\r\n);
// - Linux LF (\n);
// - OSX CR (\r).
// And that's why single dollar meta assertion ($) sometimes fails with multiline modifier (/m) mode - possible bug in PHP 5.3.8 or just a "feature"(?).
$str="ABC ABC\n\n123 123\r\ndef def\rnop nop\r\n890 890\nQRS QRS\r\r~-_ ~-_";
// C 3 p 0 _
$pat1='/\w$/mi'; // This works excellent in JavaScript (Firefox 7.0.1+)
$pat2='/\w\r?$/mi'; // Slightly better
$pat3='/\w\R?$/mi'; // Somehow disappointing according to php.net and pcre.org when used improperly
$pat4='/\w(?=\R)/i'; // Much better with allowed lookahead assertion (just to detect without capture) without multiline (/m) mode; note that with alternative for end of string ((?=\R|$)) it would grab all 7 elements as expected
$pat5='/\w\v?$/mi';
$pat6='/(*ANYCRLF)\w$/mi'; // Excellent but undocumented on php.net at the moment (described on pcre.org and en.wikipedia.org)
$n=preg_match_all($pat1, $str, $m1);
$o=preg_match_all($pat2, $str, $m2);
$p=preg_match_all($pat3, $str, $m3);
$r=preg_match_all($pat4, $str, $m4);
$s=preg_match_all($pat5, $str, $m5);
$t=preg_match_all($pat6, $str, $m6);
echo $str."\n1 !!! $pat1 ($n): ".print_r($m1[0], true)
."\n2 !!! $pat2 ($o): ".print_r($m2[0], true)
."\n3 !!! $pat3 ($p): ".print_r($m3[0], true)
."\n4 !!! $pat4 ($r): ".print_r($m4[0], true)
."\n5 !!! $pat5 ($s): ".print_r($m5[0], true)
."\n6 !!! $pat6 ($t): ".print_r($m6[0], true);
// Note the difference among the three very helpful escape sequences in $pat2 (\r), $pat3 and $pat4 (\R), $pat5 (\v) and altered newline option in $pat6 ((*ANYCRLF)) - for some applications at least.
/* The code above results in the following output:
ABC ABC
123 123
def def
nop nop
890 890
QRS QRS
~-_ ~-_
1 !!! /\w$/mi (3): Array
(
[0] => C
[1] => 0
[2] => _
)
2 !!! /\w\r?$/mi (5): Array
(
[0] => C
[1] => 3
[2] => p
[3] => 0
[4] => _
)
3 !!! /\w\R?$/mi (5): Array
(
[0] => C
[1] => 3
[2] => p
[3] => 0
[4] => _
)
4 !!! /\w(?=\R)/i (6): Array
(
[0] => C
[1] => 3
[2] => f
[3] => p
[4] => 0
[5] => S
)
5 !!! /\w\v?$/mi (5): Array
(
[0] => C
[1] => 3
[2] => p
[3] => 0
[4] => _
)
6 !!! /(*ANYCRLF)\w$/mi (7): Array
(
[0] => C
[1] => 3
[2] => f
[3] => p
[4] => 0
[5] => S
[6] => _
)
*/
?>
Unfortunately, I haven't got any access to a server with the latest PHP version - my local PHP is 5.3.8 and my public host's PHP is version 5.2.17.
As \v matches both single char line ends (CR, LF) and double char (CR+LF, LF+CR), it is not a fixed length atom (eg. is not allowed in lookbehind assertions).
A non breaking space is not considered as a space and cannot be caught by \s.
it can be found with :
- [\xc2\xa0] in utf-8
- \x{00a0} in unicode
Note that there are (sometimes difficult to grasp at first glance) nuances of meaning and application of escape sequences like \r, \R and \v - none of them is perfect in all situations, but they are quite useful nevertheless. Some official PCRE control options and their changes come in handy too - unfortunately neither (*ANYCRLF), (*ANY) nor (*CRLF) is documented here on php.net at the moment (although they seem to be available for over 10 years and 5 months now), but they are described on Wikipedia ("Newline/linebreak options" at https://en.wikipedia.org/wiki/Perl_Compatible_Regular_Expressions) and official PCRE library site ("Newline convention" at http://www.pcre.org/original/doc/html/pcresyntax.html#SEC17) pretty well. The functionality of \R appears somehow disappointing (with default configuration of compile time option) according to php.net as well as official description ("Newline sequences" at https://www.pcre.org/original/doc/html/pcrepattern.html#newlineseq).
A hint for those of you who are trying to fight off (or work around at least) the problem of matching a pattern correctly at the end ($) of any line in multiple lines mode (/m).
<?php
// Various OS-es have various end line (a.k.a line break) chars:
// - Windows uses CR+LF (\r\n);
// - Linux LF (\n);
// - OSX CR (\r).
// And that's why single dollar meta assertion ($) sometimes fails with multiline modifier (/m) mode - possible bug in PHP 5.3.8 or just a "feature"(?).
$str="ABC ABC\n\n123 123\r\ndef def\rnop nop\r\n890 890\nQRS QRS\r\r~-_ ~-_";
// C 3 p 0 _
$pat1='/\w$/mi'; // This works excellent in JavaScript (Firefox 7.0.1+)
$pat2='/\w\r?$/mi';
$pat3='/\w\R?$/mi'; // Somehow disappointing according to php.net and pcre.org
$pat4='/\w\v?$/mi';
$pat5='/(*ANYCRLF)\w$/mi'; // Excellent but undocumented on php.net at the moment
$n=preg_match_all($pat1, $str, $m1);
$o=preg_match_all($pat2, $str, $m2);
$p=preg_match_all($pat3, $str, $m3);
$r=preg_match_all($pat4, $str, $m4);
$s=preg_match_all($pat5, $str, $m5);
echo $str."\n1 !!! $pat1 ($n): ".print_r($m1[0], true)
."\n2 !!! $pat2 ($o): ".print_r($m2[0], true)
."\n3 !!! $pat3 ($p): ".print_r($m3[0], true)
."\n4 !!! $pat4 ($r): ".print_r($m4[0], true)
."\n5 !!! $pat5 ($s): ".print_r($m5[0], true);
// Note the difference among the three very helpful escape sequences in $pat2 (\r), $pat3 (\R), $pat4 (\v) and altered newline option in $pat5 ((*ANYCRLF)) - for some applications at least.
/* The code above results in the following output:
ABC ABC
123 123
def def
nop nop
890 890
QRS QRS
~-_ ~-_
1 !!! /\w$/mi (3): Array
(
[0] => C
[1] => 0
[2] => _
)
2 !!! /\w\r?$/mi (5): Array
(
[0] => C
[1] => 3
[2] => p
[3] => 0
[4] => _
)
3 !!! /\w\R?$/mi (5): Array
(
[0] => C
[1] => 3
[2] => p
[3] => 0
[4] => _
)
4 !!! /\w\v?$/mi (5): Array
(
[0] => C
[1] => 3
[2] => p
[3] => 0
[4] => _
)
5 !!! /(*ANYCRLF)\w$/mi (7): Array
(
[0] => C
[1] => 3
[2] => f
[3] => p
[4] => 0
[5] => S
[6] => _
)
*/
?>
Unfortunately, I haven't got any access to a server with the latest PHP version - my local PHP is 5.3.8 and my public host's PHP is version 5.2.17.