sed 中的lookbehind 工作吗?

发布于 2025-01-14 16:06:35 字数 273 浏览 4 评论 0原文

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

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

通过返回 bar 可以正常工作。

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

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

I created a test using grep but it does not work in sed.

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

This works correctly by returning bar.

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

I was expecting footest as output, but it did not work.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

眼前雾蒙蒙 2025-01-21 16:06:36

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

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

GNU sed does not have support for lookaround assertions. You could use a more powerful language such as Perl or possibly experiment with ssed which supports Perl-style regular expressions.

perl -pe 's/(?<=foo)bar/test/g' file.txt
停顿的约定 2025-01-21 16:06:36

sed 不支持环视,但 choose (我是作者)支持。它使用 PCRE2 语法。

例如:

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

它的速度可比 sed。

sed doesn't support lookarounds but choose (I'm the author) does. It uses PCRE2 syntax.

For example:

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

It's speed is comparable to sed.

年华零落成诗 2025-01-21 16:06:36

Powershell 的 -replace 支持前瞻:

(Get-Content -Raw file.tsv) -replace '(?<=\t)\\N(?=\t)','' | Set-Content file.tsv

它会在 7 秒内从空 tsv 单元格中删除 900mb 文件的 \N。但要小心可能转换的换行符。

Powershell's -replace supports lookaheads:

(Get-Content -Raw file.tsv) -replace '(?<=\t)\\N(?=\t)','' | Set-Content file.tsv

It removes \N from empty tsv cells for 900mb file in 7s. But beware of possibly converted line breaks.

小傻瓜 2025-01-21 16:06:35

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

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

模拟负后向查找更加微妙,需要多次替换来保护您想要避免的子字符串。 (? 示例:

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

但是字符越多,它很快就会变得乏味。

Note that most of the time you can avoid a lookbehind (or a lookahead) using a capture group and a backreference in the replacement string:

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

Simulating a negative lookbehind is more subtile and needs several substitutions to protect the substring you want to avoid. Example for (?<!foo)bar:

sed 's/#/##/g;s/foobar/foob#ar/g;s/bar/test/g;s/foob#ar/foobar/g;s/##/#/g' file.txt
  • choose an escape character and repeat it (for example # => ##).
  • include this character in the substring you want to protect (foobar here, => foob#ar or ba => b#a).
  • make your replacement.
  • replace foob#ar with foobar (or b#a with ba).
  • replace ## with #.

Obviously, you can also describe all that isn't foo before bar in a capture group:

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

But it will quickly become tedious with more characters.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文