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

时间:2020-10-30 10:31:17

标签: bash perl awk sed

我有一个看起来像这样的文件:

Line 1

Line 2

Line 3



Line 4

Line 5



Line 6

如何使它看起来像这样:

Line 1
Line 2
Line 3

Line 4
Line 5

Line 6

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

4 个答案:

答案 0 :(得分:3)

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

\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

答案 1 :(得分:2)

在Perl中:要使用正则表达式匹配连续的换行符,则不能以逐行模式阅读。这就是为什么我们将文件插入单个字符串的原因。

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+

或者,如果您希望将其作为单线使用:

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

添加-i选项可在您满意更改按预期进行时就地编辑文件。 -i.bak保存备份。

答案 2 :(得分:0)

好吧,我自己弄清楚了:

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

答案 3 :(得分:0)

使用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,以便在下一行具有正确的值。 简而言之,我确实从每组空行中仅打印了第二个空行。