次の正規表現があるとします。
/BAR|FOO BAR/gi
そして、次の入力文字列: "FOO BAR"
「BAR」でマッチすると思っていたのですが、実は「FOO BAR」でマッチしてしまいました。どうしてこれなの?
次の正規表現があるとします。
/BAR|FOO BAR/gi
そして、次の入力文字列: "FOO BAR"
「BAR」でマッチすると思っていたのですが、実は「FOO BAR」でマッチしてしまいました。どうしてこれなの?
まず、正規表現を調べてみましょう。
"/BAR|FOO BAR/gi"
これが検索するのは、一致した文字列内のBAR
またはです。FOO BAR
フラグは ( perl正規表現に準拠していると仮定して) 'global' で 'case insensitive' です:
マッチングがどのように機能するかを理解するために、いくつかのことを試してみましょう (注:perl
最も一般的な正規表現の実装であるため、使用していますが、これらの例は、準拠している言語で機能するはずです)。
use warnings;
use strict;
my $string = "FOO BAR";
if ($string =~ /FOO/) { print "1. True\n"; } # 'FOO' matches in string
if ($string =~ /BAR/) { print "2. True\n"; } # 'BAR' matches in string
if ($string =~ /foo/i) { print "3. True\n"; } # 'foo' matches in string, ignoring case
これはtrue
、すべての 3 つのステートメント ( demo ) に対して出力されFOO
、BAR
とfoo
がすべて大文字と小文字を区別しない有効な一致であることを示します。
FOO BAR
では、正規表現が「 」ではなく「 」に一致するのはなぜBAR
ですか?
文書化されているように、パーサーは文字列内の最初の一致を照合しようとするためです。
my $string = "FOO BAR";
$string =~ /(FOO BAR|BAR)/;
print $1; # Prints 'FOO BAR'
/g
設定によって両方が一致するわけではないことに注意してください。これ/FOO BAR|BAR/
は、ルールの両側に一致するのではなく、可能な限り多くの回数、全体のルールに一致しようとするためです。' ' が一致するとすぐFOO BAR
に、文字列のその部分での一致の試行を停止し、先に進みます。
FOO BAR
と の両方を一致させたい場合はどうしますBAR
か?
この正規表現は、指定された入力文字列の「 FOO BAR
」と「 」に一致します。BAR
my $string = "FOO BAR";
$string =~ /(FOO (BAR))/;
print "$1\n"; # Prints 'FOO BAR'
print $2; # Prints 'BAR'
/g
コンテキスト内のフラグのデモンストレーション
これ/g
は、フラグを使用して、一致し、次のようFOO
になりBAR
ます。
my $string = "FOO BAR";
while($string =~ /(FOO|BAR)/g) {
print "$1\n";
}
この例FOO
は、その後にスペースが続き、BAR
任意FOO BAR
の入力文字列に一致します。
my $string = "FOO BAR";
while($string =~ /((FOO\s)?(BAR))/g) {
print "$1\n$2\n$3";
}
注: 今後の読者が同様の問題で混乱しないように、例から無関係なフラグを削除しました。