【问题标题】:What's wrong with my lookahead regex in GNU sed?我在 GNU sed 中的前瞻正则表达式有什么问题?
【发布时间】:2012-08-23 22:49:00
【问题描述】:

这就是我正在做的(简化示例):

gsed -i -E 's/^(?!foo)(.*)$/bar\1/' file.txt

我试图将bar 放在不以foo 开头的每一行前面。这是错误:

gsed: -e expression #1, char 22: Invalid preceding regular expression

怎么了?

【问题讨论】:

标签: regex linux sed regex-lookarounds


【解决方案1】:

据我所知sed 既没有前瞻也没有后视。切换到语法相似的更强大的语言,例如perl

【讨论】:

  • 一个简单的sedperl 的转换供参考:sed 's/before/after/g' /my/file => cat /my/file | perl -ne 's/before/after/g; print;'
  • @Batandwa 在 perl 中使用 cat 和管道是多余的。只需使用perl -pi -e 's/before/after/g' /my/file
  • 很遗憾没有前瞻功能。
  • 我认为这是一个错误的答案:sed 具有提供多个编辑序列的功能,正如 kkeller 的回答。
  • @Cirelli94:虽然这是一个不错的建议,但这并不是像常规(双关语)正则表达式语法那样的负面预测。
【解决方案2】:

您使用了 GNU sed 不支持的 perl 兼容正则表达式 (PCRE) 语法。 您应该根据 SED Regular-Expressions 重写您的正则表达式,或者改用 perl

请注意,SED 没有前瞻功能,因此不支持您尝试使用的正则表达式功能。正如其他人所提到的,它可以在 SED 中使用其他功能来完成。

【讨论】:

    【解决方案3】:
    sed -i '/^foo/! s/^/bar/' file.txt
    
    • -i原地改文件
    • /^foo/! 仅对以 foo ^foo 开头的非 ! 的行执行下一个操作
    • s/^/bar/ 将行首改为小节

    【讨论】:

    • 非常好的解决方案。无需回溯。只需使用 sed 已有的功能即可。
    • 这对于像^foo 这样的锚定表达式来说很好,但不幸的是,它不能扩展到模式中任何地方的否定前瞻的一般情况。
    • 但是,当行中仅存在一个替换实例时,它会扩展。例如,'s/(?!foo)baz/bar/' =>'/foobaz/! s/baz/bar/'。也许适当地应用聪明可以将这种方法扩展到包含例如“foobaz baz”的行。
    • @tripleee 这是可能的。检查this answer 的想法。
    • @Nabheet:我不确定您要删除哪些行。您的代码显示“搜索不包含 foo 的行”,然后,您没有给出命令,而是说出如何处理这些行,而是给出了另一个过滤器。那是行不通的。如果要删除所有不包含 foo 的行,请使用 '/foo/! d' 如果要删除所有不包含 foo 但包含 bar 的行,则需要在第一个过滤器之后使用块命令来应用第二个过滤器:'/foo/! {/bar/d}' 请注意,最初的问题是关于以 foo 开头的行,您通过删除 ^ 删除了它
    猜你喜欢
    • 2018-09-06
    • 2013-04-11
    • 2018-04-03
    • 1970-01-01
    • 2018-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多