lookbehind 在 sed 中工作吗?

问题描述 投票:0回答:3

我使用

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

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

返回

bar
即可正常工作。

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

我期待

footest
作为输出,但它不起作用。

regex sed grep lookbehind
3个回答
47
投票

GNU sed 不支持环视断言。您可以使用更强大的语言,例如 Perl,或者尝试使用支持 Perl 风格正则表达式的

ssed

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

46
投票

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

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#ar
    ba
    =>
    b#a
    )。
  • 进行替换。
  • foob#ar
    替换为
    foobar
    (或将
    b#a
    替换为
    ba
    )。
  • ##
    替换为
    #

显然,您还可以描述捕获组中

foo
之前不是
bar
的所有内容:

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

但是角色越多,它很快就会变得乏味。


0
投票

choose(我是作者)可以流式编辑并支持lookarounds +完整的PCRE2语法。

例如:

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

它的速度与 sed 相当

© www.soinside.com 2019 - 2024. All rights reserved.