String无法在同一行中找到该值

时间:2016-12-31 10:25:42

标签: perl

use strict;
use warnings;

my $str = "This is the test and new paragraph...\n";

if($str=~m/paragraph/gi) # First Loop
{
    if($str=~m/test/gi) # Second Loop 
    {
        print "Ok...\n";
    }
    else
    {
        print "Not Ok...\n";
    }
}

if($str=~m/test/i) #it doesn't prints the value

Output is: Not Ok...

if($str=~m/test/gi) #it prints the value

Output is: Ok...

在上述情况下,如果字符串找到paragraph值,而第二个循环找不到test值。但是在第二个循环中,如果我们插入全局g它就可以。

请问有人可以解释我发生了什么事。提前谢谢。

2 个答案:

答案 0 :(得分:2)

来自perldoc perlretut

  

全球匹配

     

我们将在这里讨论的最后两个修饰符// g和// c涉及多个匹配。修饰符// g代表全局匹配,并允许匹配运算符在字符串中尽可能多地匹配。在标量上下文中,对字符串的连续调用将具有// g从匹配跳转到匹配,跟踪字符串中的位置。您可以使用pos()函数获取或设置位置。

在第一个测试中,您使用全局标记,然后记住光标的位置,因此第二个匹配找不到test,因为它位于paragraph之前

您必须从第一场比赛中删除全局标志。

my $str = "This is the test and new paragraph...\n";

if ($str =~ /paragraph/i) {
    if ($str =~ /test/i) {
        print "Ok...\n";
    } else {
        print "Not Ok...\n";
    }
}

答案 1 :(得分:2)

/g用于查找模式的所有匹配项。改变比赛之间的模式没有意义。一般来说,if (/.../g)毫无意义,应替换为if (/.../)

if (/\G.../gc)有高级用途,但情况有所不同。 if (/.../g)只有在您展开while循环时才有意义。 (例如while (1) { ...; last if !/.../g; ... })。

这是在这种具体情况下发生的事情:

因为你发信号通知你想要找到所有匹配(使用/g),所以开始匹配的位置设置为匹配的结尾(在下面用^表示)。

This is the test and new paragraph...
                         ---------^

您可以使用pos来查看此内容。

$ perl -e'
    my $str = "This is the test and new paragraph...";
    if ($str =~ /paragraph/g) {
       CORE::say pos($str) // 0;
       if ($str =~ /test/g) {
          CORE::say pos($str) // 0;
       }
    }
'
34

后续的m/test/gi没有匹配,因为test没有出现在最后一场比赛结束的位置或之后。

解决方案是从匹配运算符中删除g修饰符。

$ perl -e'
    my $str = "This is the test and new paragraph...";
    if ($str =~ /paragraph/) {
       CORE::say pos($str) // 0;
       if ($str =~ /test/) {
          CORE::say pos($str) // 0;
       }
    }
'
0
0