代码之家  ›  专栏  ›  技术社区  ›  Jim

不能用一个空行替换多个空行

  •  1
  • Jim  · 技术社区  · 6 年前

    为什么下面的代码不能用一个空行替换多个空行?

    $ cat some_random_text.txt  
    foo   
    
    
    
    bar   
    
    
    
    
    test  
    

    但这不起作用:

    $ cat some_random_text.txt | perl -pe "s/\n+/\n/g"
    foo  
    
    
    
    bar  
    
    
    
    
    
    test  
    

    我正在尝试将多个新行(即空行)替换为一个空行,但我用于此操作的regex不能像您在示例片段中看到的那样工作。
    我搞砸了什么?

    foo
    
    bar
    
    test
    
    3 回复  |  直到 6 年前
        1
  •  6
  •   melpomene    6 年前

    它不起作用的原因是 -p 告诉perl逐行处理输入,并且没有超过一个 \n

    更好的主意:

    perl -00 -lpe 1
    
    • -00 :启用段落模式(输入记录由2+换行的任意序列终止)。
    • -l :启用autochomp模式(输入记录分隔符将自动修剪,因此由于我们处于段落模式,因此将删除所有后续换行符,并且输出记录将 "\n\n"
    • -第页 :启用自动输入/输出(主代码对每个输入记录执行;任何留在 $_ 自动打印)。
    • -e 1 :使用不执行任何操作的虚拟主程序。

        2
  •  2
  •   dawg    6 年前

    鉴于:

    $ echo "$txt"
    foo   
    
    
    
    bar   
    
    
    
    
    test  
    

    sed 将空白行的行数减少为一行 \n :

    $ echo "$txt" | sed '/^$/N;/^\n$/D'
    foo   
    
    bar   
    
    test  
    

    更简单的是,你可以使用 cat -s :

    $ echo "$txt" | cat -s            # same output 
    

    perl 惯用的一行是 -00

    $ echo "$txt" | perl -00pe0       # same output 
    

    awk 您可以灵活设置段落模式。 RS= 然后设置 ORS= \n个 成为:

    $ echo "$txt" | awk '1' RS= ORS="\n\n"    # same output 
    

    printf 'a\n\n' | ... 将产生两个具有这些解的尾随空间。这可能是问题,也可能不是问题。

        3
  •  2
  •   ikegami Gilles Quénot    6 年前

    您正在执行以下程序:

    LINE: while (<>) {
       s/\n+/\n/g;
    }
    continue {
       die "-p destination: $!\n" unless print $_;
    }
    

    因为一次只读取一行,而且一行是一个字符序列,不是以换行符结尾的换行符,所以模式永远不会匹配多个换行符。


    简单的解决方法是告诉Perl将整个文件视为一行。另外,您不希望替换每个换行符,而只替换那些在两个或更多换行符序列中找到的换行符,您希望用两个换行符替换序列。

    perl -0777pe's/\n\n\K\n+//g; s^\n+//; s/\n\K\n\z//' some_random_text.txt
    

    第二次和第三次替换确保文件的开头和结尾没有空行。


    虽然将整个文件读入内存很容易,但这是不必要的。还可以通过维护一个标志来实现所需的输出,该标志指示前一行是否为空。

    perl -ne'if (/\S/) { print "\n" if $f; print; $f=0 } else { $f=1 }' some_random_text.txt
    

    此解决方案还将删除文件开头和结尾的空行。