【问题标题】:How to inplace substitute the content between 2 tags with SED (bash)?如何用 SED (bash) 替换 2 个标签之间的内容?
【发布时间】:2021-07-02 23:17:33
【问题描述】:

我想用sed (Oracle-Linux/Bash) 就地编辑文件。

两个搜索标签之间的内容(以“#”-cmets 的形式)应该被注释掉。

例子:

Some_Values
#NORMAL_LISTENER_START
LISTENER =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = IPC)
         (KEY      = LISTENER)
    )
  )
)
#NORMAL_LISTENER_END
Other_Values

应该导致:

Some_Values    
#NORMAL_LISTENER_START
# LISTENER =
#   (DESCRIPTION =
#     (ADDRESS = (PROTOCOL = IPC)
#          (KEY      = LISTENER)
#     )
#   )
# )
#NORMAL_LISTENER_END
Other_Values

下面的命令已经实现了,但是它还在search-tags前面放了一个comment+blank:

sed -i "/#NORMAL_LISTENER_START/,/#NORMAL_LISTENER_END/ s/^/# /" ${my_file}

现在我的研究告诉我要排除那些搜索标签,例如:

sed -i '/#NORMAL_LISTENER_START/,/#NORMAL_LISTENER_END/{//!p;} s/^/# /' ${my_file}

但它不起作用 - 结果显示以下消息:

sed: -e 表达式 #1, char 56: 命令后的多余字符

我需要这些 SearchTag 保持原样,因为之后我再次需要它们。

【问题讨论】:

    标签: awk sed


    【解决方案1】:

    如果ed 可用/可接受。

    printf '%s\n' 'g/#NORMAL_LISTENER_START/+1;/#NORMAL_LISTENER_END/-1s/^/#/' ,p Q | ed -s file.txt
    
    • 如果您对输出感到满意,请将Q 更改为w,并且将进行就地编辑

    • 如果您不想看到输出,请删除,p

    【讨论】:

      【解决方案2】:

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

      sed '/#NORMAL_LISTENER_START/,/#NORMAL_LISTENER_END/{//!s/^/# /}' file
      

      使用由两个正则表达式分隔的范围,并在正则表达式之间的行之前插入# ,但不包括正则表达式。

      替代方案:

      sed '/#NORMAL_LISTENER_START/,/#NORMAL_LISTENER_END/{s/^[^#]/# &/}' file
      

      或者,如果您愿意:

      sed '/#NORMAL_LISTENER_START/{:a;n;/#NORMAL_LISTENER_END/!s/^/# /;ta}' file
      

      【讨论】:

        【解决方案3】:

        仅使用您展示的示例,请尝试遵循awk 代码。简单的解释是,按照那个查找特定的字符串和设置/取消设置变量,然后按照那个打印更新(在行中添加 #)行,一旦我们找到不需要更新行的行,就停止更新行。

        awk ' /Other_Values/{found=""} found{$0=$0!~/^#/?"#"$0:$0} /Some_Values/{found=1} 1' Input_file
        

        上面将在终端上打印输出,一旦您对结果感到满意,您可以运行以下代码来就地保存到 Input_file。

        awk ' /Other_Values/{found=""} found{$0=$0!~/^#/?"#"$0:$0} /Some_Values/{found=1} 1' Input_file > temp && mv temp Input_file
        

        说明:为上述添加详细说明。

        awk '                                    ##Starting awk program from here.
        /Other_Values/{ found=""             }   ##If line contains Other_Values then nullify found here.  
        found        {  $0=$0!~/^#/?"#"$0:$0 }   ##If found is SET then check if line already has # then leave it as it is OR add # in starting to it.
        /Some_Values/{ found=1               }   ##If line contains Some_Values then set found here.
        1                                        ##Printing current line here.
        ' Input_file                             ##Mentioning Input_file name here.
        

        【讨论】:

        • 一切正常 - 创建临时文件有点难看。没有它有没有办法做到这一点?
        • @Dannxy,当然,在 GNU Awk 4.1.0(2013 年发布)及更高版本中,它具有就地编辑选项,然后尝试以下操作:gawk -i inplace ' /Other_Values/{found=""} found{$0=$0!~/^#/?"#"$0:$0} /Some_Values/{found=1} 1' Input_file
        • @Dannxy,我现在也在我的解决方案中添加了详细的解释。
        • 似乎我们必须使用 GNU Awk 4.0.2 - 所以我必须坚持使用临时文件。但没关系,你拯救了我的一天。谢谢!问候!
        猜你喜欢
        • 2014-09-29
        • 1970-01-01
        • 1970-01-01
        • 2011-11-03
        • 1970-01-01
        • 2015-01-09
        • 1970-01-01
        • 2020-10-30
        • 1970-01-01
        相关资源
        最近更新 更多