次の正規表現があるとします。
/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";
}
注: 今後の読者が同様の問題で混乱しないように、例から無関係なフラグを削除しました。