我有一个文件 - 一个,并且存在一些连续的空行(多个),见下文:
cat a
1
2
3
4
5
首先我想知道是否存在继续空行,我试过
cat a | grep '\n\n\n'
没有输出。所以我必须使用以下方式
vi a
:set list
/\n\n\n
所以我想知道是否存在其他shell命令可以轻松实现这个? 然后,如果存在两个或更多的空行我想将它们转换为一个?见下文
1
2
3
4
5
起初我尝试了下面的shell
sed 's/\n\n\(\n\)*/\n\n/g' a
它不起作用,然后我尝试了这个shell
cat a | tr '\n' '$' | sed 's/$$\(\$\)*/$$/g' | tr '$' '\n'
这次它有效。而且我想知道是否存在其他方式可以实现这个?
答案 0 :(得分:6)
好吧,如果您的cat
实施支持
-s, --squeeze-blank
suppress repeated empty output lines
然后它就像
一样简单$ cat -s a
1
2
3
4
5
此外,编号行的-s
和-n
也可能与less
命令一起使用。
备注:只包含空格的行不会被删除。
如果您的cat
不支持-s
,那么您可以使用:
awk 'NF||p; {p=NF}'
或者如果你想在每条记录后保证一个空行,包括在输出结尾,即使输入中没有,那么:
awk -v RS= -v ORS='\n\n' '1'
如果您的输入包含所有空格的行,并且您希望它们被视为非空白行(如cat -s
那样,请参阅下面的注释),然后:
awk '/./||p; {p=/./}'
并保证输出结尾处有一个空行:
awk '/./||p; {p=/./} END{if (p) print ""}'
答案 1 :(得分:3)
此awk
命令应该可以生成每行包含2个换行符的输出:
awk -v RS= '{printf "%s%s", $0, ORS (RT ~ /\n{2,}/ ? ORS : "")}' file
1
2
3
4
5
这个awk正在使用:
-v RS=
:设置空输入记录分隔符,以便每个空行成为记录分隔符printf "%s%s", $0, ORS
:使用单换行打印每一行(RT ~ /\n{2,}/ ? ORS : "")
:如果输入记录分隔符有超过2个换行符,则打印其他换行符您也可以在slurp模式下使用perl
:
perl -0777 -pe 's/\R{2,}/\n\n/g' file
1
2
3
4
5
命令分手:
-0777
Slurp模式读取整个文件's/\R{2,}/\n\n/g'
匹配2个或更多换行符并替换为2个换行符答案 2 :(得分:1)
您可--squeeze-repeats
使用tr
,然后使用sed
插入新行:
<a tr -s '\n' | sed 'G'
答案 3 :(得分:1)
备注:这是我的答案here
的副本一种非常快速的方法是使用awk
awk 'BEGIN{RS="";ORS="\n\n"}1'
这是如何工作的:
awk知道概念记录(默认情况下为几行),您可以通过其记录分隔符RS
定义记录。如果将RS
的值设置为空字符串,则它将匹配任何空行作为记录分隔符。值ORS
是输出记录分隔符。它指出应在两个连续记录之间打印哪个分隔符。设置为两个1
是{print $0}
的简写,它打印当前记录,然后打印输出记录分隔符ORS
。
注意:就像cat -s
那样,仅保留空白行作为实际行,而不会隐藏它们。
答案 4 :(得分:0)
另一个解决方案:
awk 'NF' ORS="\n\n" a
1
2
3
4
5
通过测试NF(字段数)是否为零来检查线路是否为空。它匹配,打印行作为默认动作。 ORS(输出记录分隔符)设置为2个换行符,因此非空行之间有一个空行。
答案 5 :(得分:0)
1)awk解决方案
$ echo "a\n\n\nb\n\n\nc\n\n\n" | awk 'BEGIN{b=0} /^$/{b=1;next} {printf "%s%s\n", b==1?"\n":"",$0} {b=0} END{printf "%s",b==1?"\n":""}'
a
b
c
$
2)sed解决方案
sed '
/^$/{ ${ p; d; }; H; d; }
/^$/!{ x; s/^\(\n\{1,\}\)$/\1/; ts; Tf; }
:s { x; s/\(.*\)/\n\1/; x; s/.*//; x; p; d; }
:f { x; p; d; }
'
SED说明:
/^$/{ ${ p; d; }; H; d; }
- 如果输入为空白,如果是最后一行,则只需打印,否则附加到保留空间并删除模式空间并开始新的循环
/^$/!{ x; s/^\(\n\{1,\}\)$/\1/; ts; Tf; }
- 如果输入不为空,则交换p空间和h空格的内容,并检查h空格是否包含\ n。如果是,跳转到s,如果没有跳转到f
:s { x; s/\(.*\)/\n\1/; x; s/.*//; x; p; d; }
- 如果h空格中存在空行,则将\ n附加到p空格,然后清除保留空间,然后打印p空格并删除p空格
:f { x; p; d; }
- 如果h空格中没有空行,则打印p空格并删除p空格