使用sed删除空行

500

我正在尝试使用sed删除空行:

sed '/^$/d'

但是我在这方面没有什么运气。

例如,我有以下这几行代码:

xxxxxx


yyyyyy


zzzzzz

我希望它能像这样:

xxxxxx
yyyyyy
zzzzzz

这个应该怎么编码?


5
你的sed命令看起来没问题,应该可以运行。 - perreal
即使您没有空格/制表符,上述命令也无法工作,但是如果存在CR + LF行结尾,它也无法工作。 - devnull
2
对于awk,请参见:在awk中删除空行,或者使用grep。一般来说,请参见:如何在shell中从文件中删除空行? - kenorb
17个回答

820
您的“空”行可能包含空格或制表符。使用 sed POSIX 类来删除只包含空格的所有行:
sed '/^[[:space:]]*$/d'

使用ERE的较短版本,例如使用gnu sed:

sed -r '/^\s*$/d'

(注意,sed 不支持 PCRE。)


3
@HuStmpHrrr,GNU sed根本不支持PCRE。它只支持使用“-r”的ERE。 - Kent
22
在OS X系统中需要使用命令 sed -i "" '/^[[:space:]]*$/d' 来处理名为 <filename> 的文件,该命令可以去除文件中空白行。 - jww
2
@BernieReiter ^\s*$ 将匹配所有“空”行,这里的空意味着该行不包含任何字符,或者该行仅包含空字符串(例如空格)。所有匹配的行将被 sed 的 d 命令删除。 - Kent
也许 sed '/\S/!d' file - potong
我在(GNU sed) 4.9上不需要-r标志。 - undefined

206

我不会用 awk 解决方案:

awk 'NF' file

这将返回:

xxxxxx
yyyyyy
zzzzzz
这是如何工作的?由于NF代表着“字段数量”,所以那些空行的字段数为0,因此awk将0视为False并且不打印任何行;但是,如果至少有一个字段,则评估结果为True,并使awk执行其默认操作:打印当前行。

1
哇,甚至在BSD的“最小化”版awk(版本20121220(FreeBSD))上运行。谢谢 :-) - Bernie Reiter
虽然我进行了两次 awk 的快速测试,但它的速度要快得多:`$ time (topic companies real 0m0.006s user 0m0.000s sys 0m0.008s`$ time (topic companies real 0m0.014s user 0m0.002s sys 0m0.006s您是否知道将此包含到 awk 脚本中的巧妙方法,例如模式? awk '/mypattern/ {do stuff...}' - Bernie Reiter
2
注意,这也会忽略只有空格的行。 - wisbucky
1
如果空行也包含回车字符“(\r)”,则无法正常工作。 - ychaouche
1
太酷了,谢谢。 - woland
显示剩余2条评论

99

2
这些在您的在线工具中正确显示,但是在方括号表达式中不应该被转义,所以这里的代码对于\[\[:space:\]\]\[ \t\]并不正确——应该是[[:space:]][ \t] - Benjamin W.
1
@BenjaminW。感谢您发现了这个问题。那些不是原始作者的内容,而是来自于编辑3,当它从普通文本变成“代码”时,就“暴露”了\\转义。我已经修复了它们。 - wisbucky

84

是的。我正在修改一个文件。*.csv。sed命令中应该如何放置-i? - jonas
4
sed -i '/^$/d' 是一种实现该功能的方式。 - Alberto Zaccagni

44

我认为这是最简单、最快速的方法:

cat file.txt | grep .
如果您需要同时忽略所有的空白行,那么可以尝试这样做:
cat file.txt | grep '\S'

例子:

s="\
\
a\
 b\
\
Below is TAB:\
    \
Below is space:\
 \
c\
\
"; echo "$s" | grep . | wc -l; echo "$s" | grep '\S' | wc -l

输出

7
5

13
不需要使用 cat 命令,grep 命令也可以直接处理文件:grep . file.txt - Ciro Santilli OurBigBook.com
3
知道了,但是最初的问题没有提到源是文件还是其他什么东西,所以解决方案在“|”之后,而在此之前只是一个源的示例。这样可以简单地区分出行的解决方案和源。 - Vadim
2
“grep '\S'” 绝对不是可移植的。如果您有“grep -P”,则可以使用“grep -P '\S'”,但它也不受所有平台的支持。 - tripleee
与其他解决方案相比,“grep .” 的缺点是会将所有文本都突出显示为红色。其他解决方案可以保留原始颜色。比较“unbuffer apt search foo | grep .” 和 “unbuffer apt search foo | grep -v ^$”。 - wisbucky
@wisbucky grep 不会默认输出彩色结果,但通常可以通过 shell 别名或环境变量启用。使用 grep --color=never . 来覆盖此设置。 - Clement Cherlin

18

另一个没有使用sedawkperl等的选项。

strings $file > $output

strings - 打印文件中可打印字符的字符串。


1
你是不是指的是 strings 而不是 string - Mickael B.
2
对于每个给定的文件,GNU strings 命令打印出至少为 4 个字符长的可打印字符序列......所以非常短的行可能会让你感到惊讶,如果你不知道这一点。有一个 --bytes=min-len 选项允许更短的行。 - SouthwindCG

17

在获得此处的采纳答案以及上面被采纳的答案的帮助下,我已经使用了:

$ sed 's/^ *//; s/ *$//; /^$/d; /^\s*$/d' file.txt > output.txt

`s/^ *//`  => left trim
`s/ *$//`  => right trim
`/^$/d`    => remove empty line
`/^\s*$/d` => delete lines which may contain white space

这完全覆盖了我的所有需求,并且完美地发挥了作用。向原始作者@Kent和@kev致敬。


8
您尝试的命令是正确的,只需使用-E标志即可。
sed -E '/^$/d'

-E 标志使 sed 捕获扩展正则表达式。更多信息请参见此处


这个特定的正则表达式中没有任何需要使用“-E”标志的内容。 - tripleee

5

您可以这样说:

sed -n '/ / p' filename    #there is a space between '//'

意思是“打印除空行之外的所有行”,并保持安静。 - Timo

4

您可能看到了意外的行为,这是因为您的文本文件是在Windows上创建的,所以行尾序列是\r\n。在运行sed之前,您可以使用dos2unix将其转换为UNIX风格的文本文件,或者使用其他方法。

sed -r "/^\r?$/d"

无论是否存在回车符,都可以删除空行。


嗨,-r 标志是做什么的?是否可以将其与 -i 结合使用以直接修改文件并避免在屏幕上打印。此外,我认为这个命令也可以写成 sed -r "/^\r$/d" - Alexander Cska

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接