2

假设我有以下正则表达式:

/BAR|FOO BAR/gi

以及以下输入字符串:“FOO BAR”

我希望在“BAR”上得到匹配,但实际上我在“FOO BAR”上得到匹配。为什么是这样?

4

2 回答 2

6

正则表达式将首先查找匹配的模式

首先,让我们检查一下您的正则表达式:

"/BAR|FOO BAR/gi"

这搜索的是匹配的字符串BARFOO BAR匹配的字符串。标志(假设符合正则表达式)是“全局”和“不区分大小写”:

  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 )打印,证明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标志,将匹配FOOBAR

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 回答
5

正则表达式从头开始。它看到F, 并尝试将其与BAR选项匹配。这当然失败了。然后它会尝试该FOO BAR选项,这似乎有效,因此它运行该选项以确定它是否有效。果然,它确实如此,所以匹配是FOO BAR.

于 2013-08-22T14:14:43.800 回答