【问题标题】:Sed command : how to replace if exists else just insert? [duplicate]Sed 命令:如果存在则如何替换,否则只插入? [复制]
【发布时间】:2012-10-12 10:01:28
【问题描述】:

我需要编辑文件中的几行,以便 如果一行以 (av 或 avpgw) 开头,则将其替换为新文本, 否则只需在开头插入新文本。

如何使用 sed 做到这一点?

【问题讨论】:

    标签: linux sed


    【解决方案1】:

    我的回答只是对Olaf 的优秀解决方案above 的一个小小的澄清。

    如果您使用的是 OSX(对我来说,使用 Catalina,它使用 sed 的 2005 非 GNU 版本),并且您尝试使用他更简洁的基于分号的解决方案(在下面重复,用1/2/3 结束):

    sed 's/^avpgw/new text 1/; t; s/^av/new text 2/; t; s/^/new text 3/' file
    

    ...由于将t 命令与分号 [;](它们本身与命令的其余部分由常规 空格):

    sed: 1: "s/^avpgw/new text 1/; t ...": undefined label '; s/^av/new text 2/; t; s/^/new text 3/'
    

    这个问题和一个解决方案描述在:sed “undefined label” on MacOS

    以下是适用于 OSX 的 Olaf 的“一体化命令”解决方案的一个版本。 \n 字符是否真的比仅使用额外的 -es 更好,这是值得商榷的。除了大声笑:我发帖主要是因为我想分享这个问题的“根本原因”,这样使用 OS X 的人就不会因为他们的 sed 版本不正确支持 @ 而发疯987654332@ 命令稳健——这只是分号与换行符的问题,仅此而已!

    测试文件:

    bash-3.2$ cat file
    + cat file
    something
    avpgw something else
    av another thing
    text
    

    原始命令,在 OS X 上执行:

    bash-3.2$ sed 's/^avpgw/new text 1/; t; s/^av/new text 2/; t; s/^/new text 3/' file
    
    sed: 1: "s/^avpgw/new text 1/; t ...": undefined label '; s/^av/new text 2/; t; s/^/new text 3/'
    

    用换行符代替分号:

    bash-3.2$ sed $'s/^avpgw/new text 1/\nt\ns/^av/new text 2/\nt\ns/^/new text 3/' file
    
    new text 3something
    new text 1 something else
    new text 2 another thing
    new text 3text
    

    【讨论】:

      【解决方案2】:

      你可以这样做:

      sed -e 's/^avpgw/new text/' -e t -e 's/^av/new text/' -e t -e 's/^/new text/' file
      

      这会将模式替换为new text (s///) 并跳转到末尾 (t)。否则它会尝试下一个模式。另见sed commands summary

      你也可以用;分隔命令:

      sed 's/^avpgw/new text/; t; s/^av/new text/; t; s/^/new text/' file
      

      或将命令放在 sed 命令文件中:

      s/^avpgw/new text/
      t
      s/^av/new text/
      t
      s/^/new text/
      

      这样称呼它:

      sed -f commandfile file
      

      如果您想忽略大小写,请在替换命令的末尾附加一个 i,如 s/^av/new text/i。另一种方法是用字符集s/^[aA][vV]/new text/ 拼出来。但这不是sed 特定的,为此您可以搜索一般的正则表达式。

      【讨论】:

      • 感谢您的回复。它工作得很好。有没有办法让它不区分大小写。我的意思是Av,AV,av等都应该被替换。
      • @user1765709 您可以使用字符集或添加修饰符。请参阅我修改后的答案。
      • @Dobler 我不知道,可能是不同的sed 或其他版本。 sed --version 说什么?
      • 'sed -e t' 是什么意思?
      • @ChanKim 正如答案中所写:“并跳到末尾(t)。”
      【解决方案3】:

      这可能对你有用(GNU sed):

      sed -r 's/^av(pgw)?.*/replacement/;t;s/^/replacement /' file
      

      【讨论】:

      • @JanitoVaqueiroFerreiraFilho 好点。 GNU sed 还提供了可选的元字符?,这意味着相同的 0 或 1。但如果没有字符串 avpgwpgw * 的机会就可以了。
      • 谢谢!我想这完全取决于我们对输入的信任程度 =)
      • 谢谢。我只是想替换前缀部分(avpgw 等)而不是整个文本。在稍作修改后,它工作得非常好。有没有办法让它不区分大小写。我的意思是Av,AV,av等都应该被替换。
      猜你喜欢
      • 2013-08-06
      • 1970-01-01
      • 2015-07-04
      • 1970-01-01
      • 1970-01-01
      • 2014-11-29
      • 2011-04-30
      • 1970-01-01
      • 2018-09-17
      相关资源
      最近更新 更多