用一个换行符替换两个换行符,用两个换行符替换两个以上的换行符

Replace two newlines with a single one and more than two with two newlines

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

Line 1

Line 2

Line 3



Line 4

Line 5



Line 6

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

Line 1
Line 2
Line 3

Line 4
Line 5

Line 6

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

好吧,我自己想通了:

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

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

\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代表“空白”,包含一行中遇到的空白行数。

参见

在 Perl 中:要使用正则表达式匹配连续的换行符,您不能在 line-by-line 模式下阅读。这就是我们将文件压缩成一个字符串的原因。

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

替换正则表达式匹配单个换行符 \n,后跟一个可选的换行符 \n?,它保留 \K,后跟 1 个或多个换行符 \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+

或者如果您喜欢 one-liner:

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

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

使用awk的解决方案:

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

说明:要决定是否打印当前行,我需要知道前两行的内容——我将其保留为 minus2minus1。在 BEGIN 中我设置了它们(可以使用任何值,即 !="")。以上可能会在 pseudo-code 中显示如下 对于每一行 do:

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

然后我更新 minus1minus2 以便下一行具有正确的值。 简单地说,我只打印了每组空行中的第二个空行。