regex 在sed中可以使用lookbehind吗?

wljmcqd8  于 12个月前  发布在  其他
关注(0)|答案(3)|浏览(104)

我使用grep创建了一个测试,但它在sed中不起作用。

grep -P '(?<=foo)bar' file.txt

这通过返回bar正确工作。

sed 's/(?<=foo)bar/test/g' file.txt

我期待footest作为输出,但它没有工作。

oogrdqng

oogrdqng1#

GNU sed不支持lookaroundAssert。您可以使用功能更强大的语言,如Perl,或者尝试使用支持Perl风格正则表达式的ssed

perl -pe 's/(?<=foo)bar/test/g' file.txt
clj7thdc

clj7thdc2#

请注意,大多数情况下,您可以使用捕获组和替换字符串中的反向引用来避免向后查找(或向前查找):

sed 's/\(foo\)bar/\1test/g' file.txt

模拟一个负的向后看是更微妙的,需要几个替换来保护你想要避免的子串。例如(?<!foo)bar

sed 's/#/##/g;s/foobar/foob#ar/g;s/bar/test/g;s/foob#ar/foobar/g;s/##/#/g' file.txt
  • 选择一个转义字符并重复它(例如# => ##)。
  • 在你想要保护的子字符串中包含这个字符(这里是foobar,=> foob#arba => b#a)。
  • 找人接替你
  • foob#ar替换为foobar(或将b#a替换为ba)。
  • ##替换为#

显然,您还可以在捕获组中描述bar之前所有不是foo的内容:

sed -E 's/(^.{0,2}|[^f]..|[^o].?)bar/\1test/g' file.txt

但它会很快变得乏味与更多的字符。

56lgkhnf

56lgkhnf3#

sed不支持lookarounds,但choose(我是作者)支持。它使用PCRE2语法。
举例来说:

$ echo "hello bar foobar" | choose -r --sed '(?<=foo)bar' --replace test
hello bar footest

它的速度与sed相当。

相关问题