假设我有以下正则表达式:
/BAR|FOO BAR/gi
以下输入字符串:“FOO BAR”
我希望在“BAR”上获得一场比赛,但实际上我在“FOO BAR”上获得了一场比赛。这是为什么?
答案 0 :(得分:6)
首先,让我们检查你的正则表达式:
"/BAR|FOO BAR/gi"
搜索的内容是匹配字符串中的BAR
或FOO BAR
。标志(假设perl正则表达式符合性)是'全局'和'不区分大小写':
让我们尝试一些事情来理解匹配是如何工作的(注意:我正在使用perl
,因为它是最受欢迎的正则表达式实现,但这些示例应该适用于您的语言,如果它符合< / em>的):
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
这将为所有3个语句(demo)打印true
,证明FOO
,BAR
和foo
都是带有忽略大小写标志的有效匹配
那么,为什么您的正则表达式匹配“FOO BAR
”而不是“BAR
”?
因为,如文档所述,解析器将try to match the earliest match in the string。
my $string = "FOO BAR";
$string =~ /(FOO BAR|BAR)/;
print $1; # Prints 'FOO BAR'
请注意,设置/g
不会导致两者匹配,因为它会尝试尽可能多地匹配ENTIRE规则/FOO BAR|BAR/
,而不是匹配规则的每一侧。只要“FOO BAR
”匹配,它就会停止尝试匹配字符串的该部分并继续前进。
如果您想同时匹配FOO BAR
和BAR
,您会怎么做?
This regular expression会匹配“FOO BAR
”和“BAR
”:
my $string = "FOO BAR";
$string =~ /(FOO (BAR))/;
print "$1\n"; # Prints 'FOO BAR'
print $2; # Prints 'BAR'
在上下文中展示/g
标志
/g
标记的 This将匹配FOO
和BAR
:
my $string = "FOO BAR";
while($string =~ /(FOO|BAR)/g) {
print "$1\n";
}
This example都会匹配FOO
后跟空格BAR
和FOO BAR
。
my $string = "FOO BAR";
while($string =~ /((FOO\s)?(BAR))/g) {
print "$1\n$2\n$3";
}
注意:我已从示例中删除了不相关的标记,以免混淆未来读者遇到的类似问题。
答案 1 :(得分:5)
正则表达式从一开始就开始。它会看到F
,并尝试将其与BAR
选项进行匹配。这当然失败了。然后它尝试FOO BAR
选项,这似乎有效,所以它运行它以查明它是否有效。果然,确实如此,因此匹配为FOO BAR
。