【问题标题】:sed - Commenting a line matching a specific string AND that is not already commented outsed - 注释与特定字符串匹配且尚未注释掉的行
【发布时间】:2013-08-02 15:41:39
【问题描述】:

我有以下测试文件

AAA
BBB
CCC

使用下面的 sed 我可以注释掉 BBB 行。

# sed -e '/BBB/s/^/#/g' -i file

如果该行的开头没有#,我只想注释掉它。

# sed -e '/^#/! /BBB/s/^/#/g' file

sed: -e expression #1, char 7: unknown command: `/'

有什么想法可以实现这一点吗?

【问题讨论】:

    标签: regex sed


    【解决方案1】:

    如果您不仅要注释掉“BBB”的完全匹配,还要注释掉中间某处有“BBB”的行,您可以使用以下解决方案:

    sed -E '/^([^#].*)?BBB/  s/^/#/'
    

    这不会改变任何已经被注释掉的字符串。

    【讨论】:

      【解决方案2】:

      评论所有“BBB”,如果还没有评论。

      sed -i '/BBB/s/^#\?/#/' file
      

      【讨论】:

        【解决方案3】:

        我发现这个解决方案效果最好。

        sed -i '/^[^#]/ s/\(^.*BBB.*$\)/#\ \1/' file
        

        无论有多少个“#”符号,它都不会再添加一个。如果您要搜索的模式不包含“#”,它会将其添加到行首,并且还会添加一个尾随空格。

        如果您不想要尾随空格

        sed -i '/^[^#]/ s/\(^.*BBB.*$\)/#\1/' file
        

        【讨论】:

        • 您可能想要替换“!”使用“^”,否则这是比官方答案更好的解决方案
        【解决方案4】:

        在对原始副本进行更改之前,我通常会提供 sed-i.bak 来备份文件:

        sed -i.bak '/BBB/ s/^#*/#/' file

        这样完成后,我同时拥有filefile.bak,只有在我有信心之后才能决定删除file.bak

        【讨论】:

          【解决方案5】:

          假设 BBB 位于一行的开头,我最终使用了一个更简单的表达式:

          sed -e '/^BBB/s/^/#/' -i file
          

          为未来的我再写一封信。不要忽视-i。因为这行不通:sed -e "..." same_file > same_file

          【讨论】:

            【解决方案6】:

            另一个使用& 特殊字符的解决方案,它引用了模式空间的整个匹配部分。它比捕获和引用正则表达式组更简单/更干净。

            sed -i 's/^[^#]*BBB/#&/' file
            

            【讨论】:

            • 非常感谢!
            【解决方案7】:

            实际上,您不需要感叹号 (!),因为插入符号已经否定了方括号内的任何内容,并将忽略搜索中的所有井号。这个例子对我有用:

            sed -i '/[^#]/ s/\(^.*BBB.*$\)/#\ \1/' file

            【讨论】:

              【解决方案8】:

              sed -i '/![^#]/ s/\(^.*BBB.*$\)/#\ \1/' file

              这对我来说不适用于关键字 *.sudo,根本没有 cmets...

              只有以下语法有效: sed -e '/sudo/ s/^#*/#/' file

              【讨论】:

                【解决方案9】:

                假设您没有包含多个 #s 的任何行,这将起作用:

                sed -e '/BBB/ s/^#*/#/' -i file
                

                注意:您不需要 /g,因为您每行最多进行一次替换。

                【讨论】:

                • 这将始终将匹配行编辑为以单个 # 开头。因此,如果它在此命令之后以三个#s 开头,它将“清理”它以仅以一个# 开头。如果这是一个问题,为了缓解这个问题,只需相应地更改匹配部分(例如sed -e '/^BBB/...)
                • sed '/^#BBB/' 你的意思是。但是,如果 BBB 位于中间的某个位置,则它将不起作用。有一个选项可以写sed '/^#/! {/BBB/ s/^/#/}',它会更好地工作,但只要你知道它的局限性,我的初始解决方案就更简单了。
                • 如果我们在java程序中使用上面的如何逃避这个?
                • 像这样:sed -e '/BBB/ s|^(//)*|//|' -i file。请注意,它仅适用于单类 cmets,假定注释从行首开始,并将用单个 // 替换多个 pairs //
                • 是否可以将 BBB 放入输入变量中?
                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2013-05-23
                • 2014-05-18
                • 1970-01-01
                • 2014-09-13
                • 2014-06-08
                相关资源
                最近更新 更多