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

时间:2015-03-03 22:12:33

标签: regex

在之前的question中,我要求匹配遵循特定模式的字符。为了更具体,我想考虑这个例子:

我们希望匹配xb后面的所有d。我们可能希望将这些字符替换为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 个答案:

答案 0 :(得分:3)

正确的正则表达式是:

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

Check this demo

根据regex101描述:

\G - 在上一场比赛结束时或第一场比赛的字符串开头处断言位置。 \G会匹配第一场比赛的开头,因此这里需要负面预测(?!^)

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

答案 1 :(得分:-2)

我建议不要在一个正则表达式中执行此操作。如果你这样做,你的意图会更加明确:

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]/;