【问题标题】:replacing multiple line pattern in sed替换sed中的多行模式
【发布时间】:2018-09-28 04:31:09
【问题描述】:

我只是想做以下事情

替换

EXTRATHING {
};

通过

SOMETHING {};

在输入文件中。为此,我尝试了

sed -e 's/EXTRATHING {\n};/SOMETHING/' input_file.txt  >outfile.txt

这不起作用。有人可以建议使用 sed 执行此操作的正确方法是什么?

【问题讨论】:

    标签: sed


    【解决方案1】:
    sed -n '1h;1!H;${;g;s/EXTRATHING {\n};/SOMETHING {};/g;p;}' input_file.txt
    

    会做的。

    问题在于它将整个输入字符串存储在 sed 的缓冲区中。

    请参阅sed and Multi-Line Search and Replace 了解更多信息和更高效的版本。

    【讨论】:

    • 这是一个很好的答案。您在sed 中展示了正确的方法,但您也描述了缺点。使用sed 与大文件进行多行匹配在计算上可能会很昂贵。在这种情况下(非常大的文件),我认为最好的办法是使用perl 解决方案,例如@MasterYoda 的one。我个人已将perl 0777 更改为多行匹配,而不是sed -n。我抗拒了一段时间,但好处是值得的。
    【解决方案2】:
     sed -i.bak '/EXTRATHING/{N;s//SOMETHING/;s/\n//}' input_file.txt
    

    【讨论】:

      【解决方案3】:

      sed -e '/begin/,/end/{s/begin/replacement/p;d}'

      【讨论】:

      • 你能解释一下吗?谢谢。 :)
      • 我认为这是基于对问题的错误理解。
      • 不不,这正是我来这里寻找的。对于以begin 开头并以end 结尾的行序列,将它们全部删除,但对于包含begin 的行也发出replacement。就问题而言,该行将是sed -e '/EXTRATHING {/,/};/{s/EXTRATHING {/SOMETHING {};/p;d}'
      【解决方案4】:
      perl -lne 's/\s*};\s*$/SOMETHING{};/g if(/\s*};\s*$/);$f=0;if(/EXTRATHING {\s*$/){next;$f=1}else{print}' your_file
      

      测试如下:

      > cat temp
      fjbwjfbw
      wefjkbwjk
      jbefwejr
      EXTRATHING {
      };
      ghekg
      jhgjk
      wefjkwngk
      EXTRATHING {
        };
      jbgvjnrg
      jbfw
      wefnkwk
      EXTRATHING {
      };
      > perl -lne 's/\s*};\s*$/SOMETHING{};/g if(/\s*};\s*$/);$f=0;if(/EXTRATHING {\s*$/){next;$f=1}else{print}' temp
      fjbwjfbw
      wefjkbwjk
      jbefwejr
      SOMETHING{};
      ghekg
      jhgjk
      wefjkwngk
      SOMETHING{};
      jbgvjnrg
      jbfw
      wefnkwk
      SOMETHING{};
      > 
      

      如果你想更改文件 inline 。添加 -i 标志。 喜欢:

      perl -i -lne '.......' your_file
      

      【讨论】:

        【解决方案5】:

        在sed中很难做到,需要写下标。 但是,您可以使用 perl 使用单行:

        perl -0777 -pe 's/EXTRATHING {\n/SOMETHING {/g' input_file.txt > outfile.txt
        

        在哪里 -0777 是记录分隔符(文本文件中的结束行) -p 为所有文件运行命令并在屏幕上打印 -e 表示这是一个单行命令

        【讨论】:

        • 尽管这个答案没有描述如何在sed 中执行答案,但我相信它是最好的答案。多行匹配不仅在perl中更容易,而且占用的计算资源也更少。
        • 澄清一下,您所指的“下标”是大括号内的代码部分,对吧?例如,@BertrandMarron 的answer 中的${;g;s/EXTRATHING {\n};/SOMETHING {};/g;p;} 就是你所说的下标,如果我理解正确的话。如果您是这个意思,请告诉我。
        【解决方案6】:

        这可能对你有用:

         sed '/^EXTRATHING {/,/^};/c\SOMETHING{}' input_file.txt >output_file.txt
        

        或者如果你想编辑原始文件:

        sed -i '/^EXTRATHING {/,/^};/c\SOMETHING{}' input_file
        

        编辑:根据要求,这是一个示例:

        cat <<! | sed '/^EXTRATHING {/,/^};/c\SOMETHING{}'
        > aaa
        > EXTRATHING {
        > };
        > bbb
        > EXTRATHING {
        > };
        > ccc
        > !
        aaa
        SOMETHING{}
        bbb
        SOMETHING{}
        ccc
        

        编辑:如果第一个和最后一个地址是连续的行,使用这个:

        # cat <<\! | sed '/^EXTRATHING {/{N;s/^EXTRATHING {\n};/SOMETHING{}/}'
        > aaa
        > EXTRATHING {
        > bbb
        > };
        > ccc
        > EXTRATHING {
        > };
        > ddd
        > !
        aaa
        EXTRATHING {
        bbb
        };
        ccc
        SOMETHING{}
        ddd
        

        另一种方式(也许更简单?):

        echo -e "EXTRATHING {\n};" | sed '$!N;s/^EXTRATHING {\n};/SOMETHING {};/;P;D'
        SOMETHING {};
        

        【讨论】:

        • 关心发布您的示例是否有效;-)?我刚把原始文档退回来了。祝你好运。
        • 谢谢@potong。但是,如果“EXTRATHING {”和“};”之间还有其他行,您的命令也会删除原始模式。我不希望那些被替换。因此,不应将以下内容替换为“EXTRATHING {\n something\n};”。
        • 谢谢,我看到您的代码适用于 sed 4*,但不适用于我在 UWIN 中的未版本控制的版本。您是否使用范围表达式来捕获这两行?即/x/,/y/?祝大家好运。
        猜你喜欢
        • 1970-01-01
        • 2017-06-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-22
        • 1970-01-01
        • 2021-09-12
        • 1970-01-01
        相关资源
        最近更新 更多