【问题标题】:Replace two newlines with a single one and more than two with two newlines [closed]用一个换行符替换两个换行符,用两个换行符替换两个以上[关闭]
【发布时间】:2021-02-12 19:33:19
【问题描述】:

我有一个如下所示的文件:

Line 1

Line 2

Line 3



Line 4

Line 5



Line 6

我怎样才能让它看起来像这样:

Line 1
Line 2
Line 3

Line 4
Line 5

Line 6

即用一个换行替换两个连续的换行符,用两个换行符替换两个以上的换行符?

【问题讨论】:

  • 这可能对你有用 GNU sed sed '/\S/!{N;//D;:a;N;//!ba;s/.*\n\n/\n/}' file

标签: bash perl awk sed


【解决方案1】:

如果我们查看换行符的序列,这就是我们想要的:

\n       -> \n    (No change)
\n\n     -> \n
\n\n\n+  -> \n\n

简单的解决方案是将整个文件加载到内存中。

perl -0777pe's/\n\n?\K\n+//g'

如果你想避免这种情况,你可以使用以下方法:

perl -ne'
   chomp;
   $b = length ? 0 : $b+1;
   CORE::say if $b==0 || $b==2;
'

$b 代表“空白”,包含一行中遇到的空白行数。

Specifying file to process to Perl one-liner

【讨论】:

    【解决方案2】:

    在 Perl 中:要使用正则表达式匹配连续的换行符,您不能在逐行模式下读取。这就是为什么我们将文件 slurp 成一个字符串。

    my $str = do { local $/; <DATA> };   # slurp the file into a single string
    $str =~ s/\n\n?\K\n+//g;             
    print $str;
    

    替换正则表达式匹配单个换行符\n,后跟一个可选换行符\n?,它保留\K,然后是一个或多个换行符\n+,它会删除它。由于所有量词都是贪婪的,这将允许? 在有 3 个或更多时保留两个换行符的大小写。

    Case     \n\n?\K\n+    explanation                   result
    \n        1 x    x     no match, no substitution     no change
    \n\n      1 0    1     match, skip, match 1 time     \n remove \n
    \n\n\n+   1 1    1+    match, match, match 1+ times  \n\n remove \n+
    

    或者,如果您喜欢它作为单线:

    perl -0777 -pe's/\n\n?\K\n+//g' file
    

    添加-i 选项以在您对更改按预期工作感到满意时就地编辑文件。 -i.bak 保存备份。

    【讨论】:

      【解决方案3】:

      好吧,我自己想通了:

      perl -0777 -i -pe 's/\n\n/\n/g' file
      

      【讨论】:

      • 这不符合问题的要求。它适用于 0-3 个空白行,但不适用于 4+
      【解决方案4】:

      使用awk的解决方案:

      awk 'BEGIN {minus2 = "a"; minus1 = "a";}{if($0==""){if(minus1=="" && minus2!=""){print $0}}else{print $0}; minus2 = minus1; minus1 = $0}' yourfile.txt
      

      说明:要决定是否打印当前行,我需要知道前两行的内容-我将其保留为minus2minus1。在BEGIN 我设置它们(可以使用任何值,!="")。上面可能会以伪代码的形式呈现如下每一行都做

      if line is empty:
          if previous line is empty and previous previous non-empty:
              print line
          else:
              do nothing
      else:
          print line
      

      然后我更新minus1minus2 以便下一行有正确的值。 简而言之,我确实从每组空行中仅打印了第二个空行。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-05-02
        • 2021-03-24
        • 2012-01-05
        • 2016-12-30
        • 2011-11-24
        • 1970-01-01
        • 2020-04-17
        • 2010-10-23
        相关资源
        最近更新 更多