了解正则表达式中的\G和\K

4
在之前的问题中,我询问了如何匹配特定模式后面的字符。为了更具体,我想考虑这个例子:
我们想匹配所有跟随 b d x 。我们可能想用 o 替换这些字符:
-a  x   x    xx x  x
-b x  x x   x   xx x
-c  x  x   x   x x x
-d x  x   x  xx x  x

结果将是这样的:
-a  x   x    xx x  x
-b o  o o   o   oo o
-c  x  x   x   x x x
-d o  o   o  oo o  o

anubhava用一条非常好的正则表达式回答了我的问题,其形式与这个相同:

/([db]|\G)[^x-]*\Kx/g

很遗憾,我并不完全理解\G\K的工作原理。我希望能够对这个特定情况进行更详细的解释。

我尝试使用Perl正则表达式调试器,但它有点晦涩难懂。

Compiling REx "([db]|\G)[^x-]*\Kx"
Final program:
   1: OPEN1 (3)
   3:   BRANCH (15)
   4:     ANYOF[bd][] (17)
  15:   BRANCH (FAIL)
  16:     GPOS (17)
  17: CLOSE1 (19)
  19: STAR (31)
  20:   ANYOF[\x00-,.-wy-\xff][{unicode_all}] (0)
  31: KEEPS (32)
  32: EXACT <x> (34)
  34: END (0)
2个回答

6

正确的正则表达式是:

(-[db]|(?!^)\G)[^x-]*\Kx

请查看该演示

根据 regex101 的描述:

\G - 断言在前一个匹配的结尾或字符串开头处进行匹配。 对于第一次匹配,\G 也将匹配行的开头,因此这里需要一个否定的前瞻 (?!^)

\K - 重置报告匹配的起始点。 任何先前使用的字符都不再包括在最终匹配中。 \K 将丢弃所有匹配的输入,因此我们可以避免在替换中使用反向引用。


-1

我建议不要在一个正则表达式中完成它。如果您这样做,您的意图会更加清晰:

if ( /^-[bd]/ ) {  # If it's a line that starts with -b or -d...
    s/x/o/g;       # ... replace the x's with o's.
}

如果这对你来说太多行了,你甚至可以这样做:
s/x/o/g if /^-[bd]/;

1
是的,这是一个不错的方法,但我的问题更多是关于单个正则表达式的一行代码,以理解\G\K - nowox
1
我点赞了这个回答,因为有时候使用多个正则表达式比起一个难以理解的单行代码更易于创建且性能更好。虽然这不是最终答案,但它确实对讨论有所贡献。 - wistlo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接