/ g modifier vs while循环

xtr*_*eak 2 regex perl

我正在解决谷歌代码堵塞问题的实践问题.每当我有同样键的字母ab11 1我曾在键入它们之间的空间.所以我将每个单独的字母转换为相应的数字序列并将它们放在一个数组中.我用':'加入了他们.每当我用':'连续分隔相同的数字时,我就用''替换它们.我使用以下正则表达式和全局修饰符.

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

产量

333 33:3 333
Run Code Online (Sandbox Code Playgroud)

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

1 while($translated =~ s/(\d+):\g{1}/$1 $1/g);
print $translated
Run Code Online (Sandbox Code Playgroud)

产量

333 33 3 333
Run Code Online (Sandbox Code Playgroud)

编辑:

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

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

amo*_*mon 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
Run Code Online (Sandbox Code Playgroud)

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

(\d+)\K[:](?=\g{-1})
Run Code Online (Sandbox Code Playgroud)

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

然后:

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

  • @Wordzilla [`perlretut`(Perl Regex Tutorial)](http://perldoc.perl.org/perlretut.html)有一个关于前瞻和外观的部分. (2认同)