为什么这个正则表达式匹配第二个项而不是第一个项

时间:2013-08-22 14:13:27

标签: regex

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

/BAR|FOO BAR/gi

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

我希望在“BAR”上获得一场比赛,但实际上我在“FOO BAR”上获得了一场比赛。这是为什么?

2 个答案:

答案 0 :(得分:6)

正则表达式将寻找与FIRST匹配的模式

首先,让我们检查你的正则表达式:

"/BAR|FOO BAR/gi"

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

  1. 全局标志表示该表达式将尝试返回all matches in the haystack
  2. 不区分大小写标志表示表达式无论大小写都匹配。
  3. 让我们尝试一些事情来理解匹配是如何工作的(注意:我正在使用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,证明FOOBARfoo都是带有忽略大小写标志的有效匹配

    那么,为什么您的正则表达式匹配“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 BARBAR,您会怎么做?

    在给定输入字符串的情况下,

    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将匹配FOOBAR

    my $string = "FOO BAR";
    
    while($string =~ /(FOO|BAR)/g) {
        print "$1\n";
    }
    

    要匹配您所寻找的......

    对于任何输入字符串,

    This example都会匹配FOO后跟空格BARFOO 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