2

次の正規表現があるとします。

/BAR|FOO BAR/gi

そして、次の入力文字列: "FOO BAR"

「BAR」でマッチすると思っていたのですが、実は「FOO BAR」でマッチしてしまいました。どうしてこれなの?

4

2 に答える 2

6

正規表現は最初に一致するパターンを探します

まず、正規表現を調べてみましょう。

"/BAR|FOO BAR/gi"

これが検索するのは、一致した文字列内のBARまたはです。FOO BARフラグは ( 正規表現に準拠していると仮定して) 'global' で 'case insensitive' です:

  1. グローバルフラグは、式がhaystack 内のすべての一致を返そうとすることを意味します。
  2. 大文字と小文字を区別しないフラグは、大文字と小文字に関係なく式が一致することを意味します。

マッチングがどのように機能するかを理解するために、いくつかのことを試してみましょう (注: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 ) に対して出力されFOOBARfooがすべて大文字と小文字を区別しない有効な一致であることを示します。

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";
}

注: 今後の読者が同様の問題で混乱しないように、例から無関係なフラグを削除しました。

于 2013-08-22T15:06:27.573 に答える