如何匹配仅遵循特定模式的第二个模式的所有模式?

时间:2016-10-21 12:22:32

标签: regex pcre

使用,我想仅在foo开头的行中将所有bar替换为foobar

输入:

foobar foo   foo                  foo       foo
foobaz    foo   foo            foo   foo foo

输出:

foobar bar   bar                  bar       bar
foobaz    foo   foo            foo   foo foo

我天真地尝试\K喜欢:

s/^foobar\Kfoo/bar/g

不幸的是它不起作用。例如,使用Perl,我可以这样做:

s/^foobar(.*)/$&=~s#\bfoo\b#bar#gr/gme

有办法吗,例如在https://regex101.com/

2 个答案:

答案 0 :(得分:1)

您可以在正则表达式中将\K\G运算符结合使用:

(?m)(?:(?!^)\G|^foobar\b)(?:(?!\bfoo\b).)*\K\bfoo\b

其中(?:(?!\bfoo\b).)* tempered greedy token.*?同义。如果在foobarfoo之间没有要排除的子字符串,.*?的效果会更好,但是,如果您想进一步限制foobarfoo之间的文字{1}},您将需要令牌。

请参阅regex demo

如果您对整个单词搜索不感兴趣,则单词边界可能会变为还原。

<强>详情:

  • (?m) -
  • 上的多线模式
  • (?:(?!^)\G|^foobar\b) - 仅匹配上一次成功匹配的结束((?!^)\G \G匹配字符串的开头或上一次成功匹配的结束,因此{{1} }必须排除字符串开头的位置)或行开头的整个单词(?!^)foobar由于^标志而匹配行起始位置)
  • (?m) - 匹配除了换行符号以外的任何字符,0 +次,如果字符未启动整个单词的(?:(?!\bfoo\b).)*序列( 或相反 只需将此部分替换为foo,因为在.*?foobar 之间没有要排除的文字。)
  • foo - 省略目前为止匹配的文字
  • \K - 整个字\bfoo\b

答案 1 :(得分:1)

是的,有了这个\ G (上一个匹配或开始后的位置)基于模式:

(?:\G(?!\A)|(?m)^foobar\b).*?\K\bfoo\b

demo