【问题标题】:replace two newlines to one in shell command line在 shell 命令行中将两个换行符替换为一个
【发布时间】:2011-11-24 00:51:42
【问题描述】:

有很多关于将多换行替换为一个换行的问题,但没有人为我工作。
我有一个文件:

first line
second line MARKER

third line MARKER
other lines

many other lines

我需要将MARKER 之后的两个换行符(如果存在)替换为一个换行符。结果文件应该是:

first line
second line MARKER
third line MARKER
other lines

many other lines

我试过sed ':a;N;$!ba;s/MARKER\n\n/MARKER\n/g' 失败。
sed 对于单行替换很有用,但换行有问题。找不到\n\n

我试过 perl -i -p -e 's/MARKER\n\n/MARKER\n/g' 失败。
这个解决方案看起来更接近,但似乎 regexp 没有对\n\n 做出反应。

是否可以仅在MARKER之后替换\n\n而不替换文件中的其他\n\n
我对单行解决方案感兴趣,而不是脚本。

【问题讨论】:

    标签: perl shell replace sed newline


    【解决方案1】:

    我认为你是在正确的轨道上。在多行程序中,您会将整个文件加载到单个标量中并在其上运行此替换:

    s/MARKER\n\n/MARKER\n/g
    

    让单行将文件加载到多行字符串中的技巧是在BEGIN 块中设置$/。此代码将在读取输入之前执行一次。

    perl -i -pe 'BEGIN{$/=undef} s/MARKER\n\n/MARKER\n/g' input
    

    【讨论】:

    • 谢谢! @ikegami 帖子较早,但您的解决方案更清晰!这正是我所要求的。
    • @oluckyman,我故意避免这个答案,因为它不必要地将整个文件加载到内存中。但由于您似乎更喜欢简短的答案,因此我在答案中添加了一个更简洁的解决方案。
    【解决方案2】:

    您的 Perl 解决方案不起作用,因为您正在搜索包含两个换行符的行。哪有这回事。这是一个解决方案:

    perl -ne'print if !$m || !/^$/; $m = /MARKER$/;' infile > outfile
    

    或就地:

    perl -i~ -ne'print if !$m || !/^$/; $m = /MARKER$/;' file
    

    如果您可以将整个文件加载到内存中,则可以使用

    perl -0777pe's/MARKER\n\n/MARKER\n/g;' infile > outfile
    

    perl -0777pe's/MARKER\n\K\n//g;' infile > outfile
    

    如上所述,您可以使用-i~ 进行就地编辑。如果您不想进行备份,请删除 ~

    【讨论】:

    • @oluckyman,它不是空的,它只包含应该被删除的空行。我的情况倒过来了。固定。
    • @oluckyman,对于每一行,1) 如果当前行前面没有标记行(通过检查 $m)或者它不是空白,则打印当前行。 2) $m 中注意当前行是否为标记行。
    • @oluckyman,第三个版本:1) 告诉 Perl 考虑整个文件一行 (-0777),然后 2) 每一行,2A) 替换前面的每个 "\n" "MARKER\n" 什么都没有,然后 2B) 打印出该行。
    【解决方案3】:

    awk:

    kent$  cat a
    first line
    second line MARKER
    
    third line MARKER
    other lines
    
    many other lines
    
    kent$  awk 'BEGIN{RS="\x034"} {gsub(/MARKER\n\n/,"MARKER\n");printf $0}' a
    first line
    second line MARKER
    third line MARKER
    other lines
    
    many other lines
    

    【讨论】:

      【解决方案4】:

      【讨论】:

      • 虽然理论上可以回答这个问题,it would be preferable 在这里包含答案的基本部分,并提供链接以供参考。鉴于该链接中有大量不相关的单行代码,这一点尤其正确。我无法通过在文档中搜索“换行符”或“\n\n”来解决这个特定问题,我希望这样的解决方案会提到。
      【解决方案5】:
      awk '
        marker { marker = 0; if (/^$/) next }
        /MARKER/ { marker = 1 }
        { print }
      '
      

      【讨论】:

        【解决方案6】:

        这可以通过非常简单的sed 来完成。

        sed '/MARKER$/{n;/./!d}'
        

        【讨论】:

          【解决方案7】:

          这可能对你有用:

           sed '/MARKER/,//{//!d}'
          

          解释:

          删除MARKER 之间的所有行,保留MARKER 行。

          或者:

          sed '/MARKER/{n;N;//D}'
          

          解释:

          读取MARKER 之后的下一行,然后追加该行。如果当前行是MARKER 行,则删除上一行。

          【讨论】:

            猜你喜欢
            • 2021-02-12
            • 1970-01-01
            • 2017-04-09
            • 1970-01-01
            • 2011-05-02
            • 2013-10-04
            • 2013-11-07
            • 2017-12-31
            • 1970-01-01
            相关资源
            最近更新 更多