【问题标题】:Sed or awk to replace a line in a blocksed 或 awk 替换块中的一行
【发布时间】:2014-06-30 07:18:56
【问题描述】:

输入文件包含:

[abc]  
para1=123  
para2=456  
para3=111  

[pqr]  
para1=333  
para2=765  
para3=1345  

[xyz]  
para1=888  
para2=236  
para3=964  

shell脚本的要求是替换特定块的一个参数
例如:将 para2=765 替换为块 [pqr]para2=999
请帮助我如何使用sedawk 命令实现此目的。

【问题讨论】:

  • 你自己做了什么?

标签: bash shell awk sed


【解决方案1】:

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

sed '/\[pqr\]/,/^\s*$/s/\(para2=\)[0-9]*/\1999/' file

在以[pqr] 开头的块中将para2= 后面的数字替换为空行。

【讨论】:

    【解决方案2】:

    惯用的 awk 解决方案是:

    $ awk 'BEGIN{RS=""; ORS="\n\n"; FS=OFS="\n"} $1=="[pqr]"{$3="para2=999"} 1' file
    [abc]
    para1=123
    para2=456
    para3=111
    
    [pqr]
    para1=333
    para2=999
    para3=1345
    
    [xyz]
    para1=888
    para2=236
    para3=964
    

    【讨论】:

      【解决方案3】:

      通过 sed 的另一种方式,

      $ sed -r ':l /^\[pqr\]/{:loop ;n;/^$/{b l};s/(para2=).*/\1999/g;b loop;}' file_name
      
      b loop   - Using the looping concept getting the line one by one.
      ^\[pqr\] - If the corresponding pattern is found.
      ^$       - Represent new line only.
      s/       - Replacement to particular pattern.
      n        - For getting next line
      

      【讨论】:

        【解决方案4】:

        我会这样做:

        awk '/^\[pqr\]/ {sub(/^para2=.*/,"para2=999")}1' RS= ORS="\n\n" file
        [abc]
        para1=123
        para2=456
        para3=111
        
        [pqr]
        para1=333
        para2=999
        para3=1345
        
        [xyz]
        para1=888
        para2=236
        para3=964
        

        通过将RS 设置为空,可以使awk 在块模式下工作,由空行分隔。
        然后通过搜索以[pqr]开头的块来确保我们在正确的块中
        在此块中,将数据从para2=765 更改为para2=999,然后打印。


        另一种方法:

        awk '/^\[pqr\]/ {f=1} f && sub(/^para2=.*/,"para2=999"){f=0}1' file
        

        如果找到pqr,则设置标志,如果标志为真,则更改数据,重置标志。

        【讨论】:

        • 感谢 Jotne 的帮助。我在想如果块之间没有行分隔符怎么办?在那种情况下如何替代?
        • @user3789290 在我的示例中使用最后一个 awk。它不需要空格或其他分隔符。
        • 您需要锚定您的 RE,否则上面的代码会将 para2=76512345 替换为 para2=99912345,例如。我怀疑 OP 只是想替换 para2= 行,不管它有什么价值。
        • Another way to do it 将失败,因为 para2 行不在 [pqr] 行之后,因此您在 sub() 有机会之前设置 f=0。您需要将其写为awk '/^\[pqr\]/ {f=1} f && sub(/^para2=.*/,"para2=999"){f=0}1' file,但也可能在找到下一个[...] 模式时注意重置f。或者您可以使用计数器来跟踪 [...] 行之后的行数并替换第二行而不是使用 sub()。
        • @EdMorton 巧妙地使用sub 作为真正的测试,我会做awk '/^\[pqr\]/ {f=1} f && /^para2/ {sub(/^para2=.*/,"para2=999");f=0}1' 你的更好,更新。
        猜你喜欢
        • 2011-01-23
        • 1970-01-01
        • 2016-10-29
        • 2021-12-07
        • 2010-10-27
        • 2016-03-13
        • 1970-01-01
        • 2020-10-29
        • 1970-01-01
        相关资源
        最近更新 更多