【问题标题】:How to insert a specific character at a specific line of a file using sed or awk?如何使用 sed 或 awk 在文件的特定行插入特定字符?
【发布时间】:2019-06-28 14:21:00
【问题描述】:

我想使用命令来编辑文件的特定行,而不是使用 vi。这就是事情。如果有以该行开头的#,则替换# 以取消注释。否则,添加 # 以使其评论。我想使用 sed 或 awk。但它不会按预期工作。
这是file

what are you doing now?
what are you gonna do? stab me?
this is interesting.
This is a test.
go big
don't be rude.

例如,我只想在第 4 行 This is a test 的开头添加 #,如果它不以 # 开头。如果它以# 开头,则删除#

我已经通过 sed & gawk (awk) 尝试过

gawk -i inplace '$1!="#" {print "#",$0;next};{print substr($0,3,length-1)}' file 
sed -i /test/s/^#// file  # make it uncomment

sed -i /test/s/^/#/ file  # make it comment

我不知道如何使用if else 使sed 工作。我只能用一个命令来完成它,然后使用另一个正则表达式来做相反的事情。
使用 gawk,它作为主线工作。但它会弄乱其余的代码。

【问题讨论】:

    标签: bash unix awk sed


    【解决方案1】:

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

    sed '4{s/^/#/;s/^##//}' file
    

    在第 4 行,将 # 添加到该行,如果有 2 个 #,则将其删除。

    也可以写成:

    sed '4s/^/#/;4s/^##//' file
    

    【讨论】:

      【解决方案2】:

      这将从第 4 行的开头删除#,如果它不存在则添加它:

      sed -i '4s/^#/\n/; 4s/^[^\n]/#&/; 4s/^\n//' File
      

      以上假设 GNU sed。如果您有 BSD/MacOS sed,则需要进行一些小的更改。

      当 sed 读取新行时,我们可以确定的关于新行的一件事是它确实包含\n。 (如果是这样,那将是两行,而不是一行。)利用这些知识,脚本的工作原理是:

      • s/^#/\n/

        如果第四行以# 开头,请将# 替换为\n。 (\n 表示该行最初已被注释掉。)

      • 4s/^[^\n]/#&/

        如果第四行现在以 \n 以外的任何内容开头(意味着它最初没有被注释),请在前面放一个 #

      • 4s/^\n//

        如果第四行现在以 \n 开头,请将其删除。

      替代方案:修改包含test的行

      评论/取消评论包含test的行:

      sed  '/test/{s/^#/\n/; s/^[^\n]/#&/; s/^\n//}' File
      

      替代方案:使用 awk

      使用 awk 可以应用完全相同的逻辑。如果我们想评论/取消评论第 4 行:

      awk 'NR==4 {sub(/^#/, "\n"); sub(/^[^\n]/, "#&"); sub(/^\n/, "")} 1' File
      

      如果我们想评论/取消评论任何包含test的行:

      awk '/test/ {sub(/^#/, "\n"); sub(/^[^\n]/, "#&"); sub(/^\n/, "")} 1' File
      

      替代方案:使用 sed 但没有换行符

      评论/取消评论任何包含test的行:

      sed  '/test/{s/^#//; t; s/^/#/; }' File
      

      它是如何工作的:

      • s/^#//; t

        如果该行以# 开头,则将其删除。

        t 告诉 sed,如果替换成功,那么它应该跳过其余的命令。

      • s/^/#/

        如果我们得到这个命令,这意味着替换没有成功(意味着该行最初没有被注释掉),所以我们插入#

      【讨论】:

      • '\n' 是关键。否则,您最终会取消您在表达式 2 :) 中对表达式 1 所做的操作(我发现 ....)
      • 是的,@DavidC.Rankin。感谢约翰的提示。哈哈。我花了 3 个小时才弄明白,直到我在这里发布问题
      • @DavidC.Rankin 你和 Alex 让我想到了它,另一种方法(不使用 \n)是使用 sed 的测试命令 t,如我刚刚添加到答案结束。
      • 这确实是一个很酷的技巧,学习已经发生。我确实记得在阅读sed 手册或信息页面时在某处看到它——但显然它从未沉入其中。只希望我能投票两次。
      • @John1024 太棒了。再次感谢您的提示。
      【解决方案3】:

      如果您最终使用不支持就地编辑的sed 系统,您可以回退到它的叔叔ed

      ed -s file 2>/dev/null <<EOF
      4 s/^/#/
      s/^##//
      w
      q
      EOF
      

      (标准错误被重定向到/dev/null,因为在ed 中,与sed 不同,如果s 不替换任何内容并且因此将问号打印到标准错误,则这是一个错误。)

      【讨论】:

        【解决方案4】:
        $ awk 'NR==4{$0=(sub(/^#/,"") ? "" : "#") $0} 1' file
        what are you doing now?
        what are you gonna do? stab me?
        this is interesting.
        #This is a test.
        go big
        don't be rude.
        
        $ awk 'NR==4{$0=(sub(/^#/,"") ? "" : "#") $0} 1' file |
          awk 'NR==4{$0=(sub(/^#/,"") ? "" : "#") $0} 1'
        what are you doing now?
        what are you gonna do? stab me?
        this is interesting.
        This is a test.
        go big
        don't be rude.
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-09-26
          • 2011-12-21
          • 1970-01-01
          • 1970-01-01
          • 2013-10-08
          • 2021-06-19
          • 1970-01-01
          相关资源
          最近更新 更多