2016-12-01 99 views
5

试图解决我的Perl脚本的问题我终于可以打破它这种情况:同样的正则表达式不匹配两次

my $content = 'test'; 
if($content =~ m/test/g) { 
    print "1\n"; 
} 
if($content =~ m/test/g) { 
    print "2\n"; 
} 
if($content =~ m/test/g) { 
    print "3\n"; 
} 

输出:

1 
3 

我的真实案例就是有点不同,但最后它是一回事:我很困惑为什么正则表达式2不匹配。有没有人对此有过解释?我意识到/ g似乎是原因,当然这在我的例子中是不需要的。但(为什么)是这种输出正常行为?

+0

from'man perlre':g和c 全局匹配,并保留 匹配失败后的当前位置。与i,m,s和x不同,这两个标志会影响 正则表达式的使用方式,而不是正则表达式本身。请参阅perlretut中的“在Perl中使用常规的 表达式”以获取g 和c修饰符的进一步解释。 – niry

回答

7

这正是标量环境中应该做的/g

它第一次匹配“测试”。第二场比赛试图在上一场比赛中止之后开始在字符串中进行匹配,并且失败。第三场比赛然后再次尝试从字符串的开头(并成功),因为第二场比赛失败,你也没有指定/c

/c如果地址不匹配,防止它重新启动之初,如果你的第二场比赛是/test/gc,第二和第三场比赛将都失败。)

+0

我只需要简短的'/ c'的详细信息,请你解释一下。 – ssr1012

+2

@ ssr1012'c - 重复匹配期间保持当前位置 – 123

+0

@ 123:真棒... – ssr1012

7

一般来说,if (/.../g)是没有意义的,应该更换与if (/.../)[1]


你不会希望以下匹配两次:

my $content = "test"; 
while ($content =~ /test/g) { 
    print(++$i, "\n"); 
} 

为什么你会想到以下匹配两次:

my $content = "test"; 
if ($content =~ /test/g) { 
    print(++$i, "\n"); 
} 

if ($content =~ /test/g) { 
    print(++$i, "\n"); 
} 

他们是一样的!


让我们想象一下$content包含testtest

  1. 的第一时间$content =~ /test/g在标量上下文进行评估,它
    匹配的第一个test
  2. 第二次$content =~ /test/g在标量环境下评估,
    它匹配第二个test
  3. 第三次$content =~ /test/g在标量上下文中进行评估,
    它返回false表示没有更多匹配。
    这也将重置未来比赛开始的位置。
  4. 第4次$content =~ /test/g在标量环境下评估,
    它匹配第一个test
  5. ...

  1. 没有关于if (/\G.../gc)采用先进,但这是不同的。if (/.../g)只有在展开一个while循环时才有意义。 (例如while (1) { ...; last if !/.../g; ... })。
+0

@ysth,这是不同的。我使用过'if(/ \ G .../gc)',但从未见过'if(/.../ g)'使用过(正确)。它只有在你展开一个while循环时才有意义。 (例如'while(1){...; last if!/.../ g;} ...}) – ikegami

+0

在我的回答中添加了一条注释来说明这一点。 – ikegami