/ g modifier vs while循环

时间:2014-05-04 09:00:45

标签: regex perl

我正在研究Google code jam problem的练习题。每当我使用与ab相同的密钥作为11 1时,我必须输入它们之间的空格。所以我将每个单独的字母转换为相应的数字序列并将它们放在一个数组中。我和'加入了他们:'。每当我将相同的数字连续分隔为':'然后我用'替换它们。 &#39 ;.我使用以下正则表达式和全局修饰符。

    my $translated = '333:33:3:333'; # edce
    $translated =~ s/(\d+):\g{1}/$1 $1/g;
    print $translated;

输出

333 33:3 333

我不得不再次使用正则表达式获取输出333 33 3 333。我有全局修饰符,但它不起作用。我尝试了一个while循环

1 while($translated =~ s/(\d+):\g{1}/$1 $1/g);
print $translated

输出

333 33 3 333

编辑:

我得到问题的解决方案我的问题是

为什么全局修饰符不起作用?

1 个答案:

答案 0 :(得分:5)

全局修饰符确实有效,但我们需要明确它的确切运作方式。

当正则表达式与/g匹配时,它会尝试从上一个匹配结束的位置开始的下一个匹配。

v-- start
333:33:3:333
 ^^^^^        1st match
      |
      v-- start
333 33:3:333
       ^^^    2nd match
          |
          v--start
333 33:3 333
              3rd match fails

您可以使用外观断言来影响哪些子字符串被视为匹配。特别是,我们可以更改正则表达式,以便只匹配:而不是周围的数字:

(\d+)\K[:](?=\g{-1})

这是如何工作的? (?=...)是零宽度前瞻。模式像往常一样匹配,但位置不会从该匹配前进。 \K运算符保持当前位置,将“忘记”先前匹配的子字符串。它类似于(?<=...) lookbehind,除了lookbehinds只能处理恒定长度的模式,这不是这里的情况。

然后:

my $str = "333:33:3:333";
$str =~ s/(\d+)\K[:](?=\g{-1})/ /g;
say $str;
# prints "333 33 3 333"