在之前的question中,我要求匹配遵循特定模式的字符。为了更具体,我想考虑这个例子:
我们希望匹配x
或b
后面的所有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)
答案 0 :(得分:3)
正确的正则表达式是:
(-[db]|(?!^)\G)[^x-]*\Kx
根据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]/;