如何从Unix文件中删除空行

56

我需要从输入文件中删除所有的空行并写入输出文件。以下是我的数据。

11216,33,1032747,64310,1,0,0,1.878,0,0,0,1,1,1.087,5,1,1,18-JAN-13,000603221321

11216,33,1033196,31300,1,0,0,1.5391,0,0,0,1,1,1.054,5,1,1,18-JAN-13,059762153003

11216,33,1033246,31300,1,0,0,1.5391,0,0,0,1,1,1.054,5,1,1,18-JAN-13,000603211032

11216,33,1033280,31118,1,0,0,1.5513,0,0,0,1,1,1.115,5,1,1,18-JAN-13,055111034001

11216,33,1033287,31118,1,0,0,1.5513,0,0,0,1,1,1.115,5,1,1,18-JAN-13,000378689701

11216,33,1033358,31118,1,0,0,1.5513,0,0,0,1,1,1.115,5,1,1,18-JAN-13,000093737301

11216,33,1035476,37340,1,0,0,1.7046,0,0,0,1,1,1.123,5,1,1,18-JAN-13,045802041926

11216,33,1035476,37340,1,0,0,1.7046,0,0,0,1,1,1.123,5,1,1,18-JAN-13,045802041954

11216,33,1035476,37340,1,0,0,1.7046,0,0,0,1,1,1.123,5,1,1,18-JAN-13,045802049326

11216,33,1035476,37340,1,0,0,1.7046,0,0,0,1,1,1.123,5,1,1,18-JAN-13,045802049383

11216,33,1036985,15151,1,0,0,1.4436,0,0,0,1,1,1.065,5,1,1,18-JAN-13,000093415580

11216,33,1037003,15151,1,0,0,1.4436,0,0,0,1,1,1.065,5,1,1,18-JAN-13,000781202001

11216,33,1037003,15151,1,0,0,1.4436,0,0,0,1,1,1.065,5,1,1,18-JAN-13,000781261305

11216,33,1037003,15151,1,0,0,1.4436,0,0,0,1,1,1.065,5,1,1,18-JAN-13,000781603955

11216,33,1037003,15151,1,0,0,1.4436,0,0,0,1,1,1.065,5,1,1,18-JAN-13,000781615746

这是我的示例数据,以下任何命令都对我不起作用。:( - Teja
1
他们没有起作用,因为你问错了问题。你真的尝试过 sed -i '/^[[:space:]]*$/d' foo 吗?因为如果这不起作用,那么你需要重新陈述问题。 - Jonathan Wakely
@SOaddict,我在这里看到了多个回答,它们回答了您最初的问题以及处理“空白”行中的空格的答案。如果这些方法都不起作用,我认为您需要检查您的输入文件并更新问题。 - gpojd
我复制粘贴了完全相同的输入文件样例。 - Teja
请查看此链接:http://theunixshell.blogspot.com/2013/01/deleting-empty-lines-from-file.html。 - Vijay
1
以下命令应该可以工作,但似乎无法正常工作的一个可能原因是文件起源于 Windows 或通过 Windows 机器中转,并且实际上具有 CRLF(回车换行)结尾,而不是 Unix 风格的 NL(换行符,又称 LF)行结尾。Unix 工具将 CR 视为另一个字符,因此像 /^$/ 这样的正则表达式将无法匹配具有 CRLF 结尾的空行。使用 sed -i '/^[[:space:]]*$/d;s/[[:space:]]*$//' 版本也适用于 CRLF 行;/^[[:space:]]*$/ 模式匹配行中的 CR。 - Jonathan Leffler
8个回答

97
sed -i '/^$/d' foo

这告诉sed删除与正则表达式^$匹配的每一行,即每一行空行。如果您的 sed 不支持就地编辑文件,则可以将输出写入临时文件并替换原始文件:-i标志。

sed '/^$/d' foo > foo.tmp
mv foo.tmp foo

如果您希望删除仅由空格组成的行(而不仅仅是空行),那么请使用:

sed -i '/^[[:space:]]*$/d' foo

编辑:同时删除行末的空格,因为显然您也决定需要这样做:

sed -i '/^[[:space:]]*$/d;s/[[:space:]]*$//' foo

8
我意识到这种可能性,所以写了“如果您的sed不支持该功能”的部分。似乎至少有七个人浪费了他们的时间试图帮助你,而你要么没有阅读要么没有正确思考。 - Jonathan Wakely
错误信息:sed: 非法选项 -- i 用法:sed [-n] [-e 脚本] [-f 源文件] [文件...] - Teja
你这19个小时都在做错事,是因为没有仔细阅读或者没有正确使用复制粘贴功能吗?唉。 - Jonathan Wakely
1
我的错,Jonathan。你的答案是正确的。昨天没有再次检查它。 - Teja
3
对于在Mac上使用-i选项遇到问题的人:使用-i .bak代替(例如sed -i .bak '/^[[:space:]]*$/d' foo)。我们使用的sed版本在进行原地编辑时需要一个文件扩展名。因此,传递-i .bak告诉它将现有文件复制并带有扩展名.bak,以便在原地编辑失败时可以还原。 - gMale
1
请注意,GNU sed 中的 -i 选项还接受备份后缀作为可选参数,因此如果您在选项和参数之间写入 -i.bak,则该代码将适用于 BSD(Mac OS X)sed 和 GNU sed。 Mac OS X 需要备份后缀,并允许它与 -i 选项分开。标准:多么美妙的事情... - Jonathan Leffler

45
awk 'NF' filename

awk 'NF > 0' filename

sed -i '/^$/d' filename

awk '!/^$/' filename

awk '/./' filename
NF也会删除只包含空格或制表符的行,但正则表达式/^ $ /不会。

如果有人感到困惑,请参考以下链接:https://dev59.com/B2Ag5IYBdhLWcg3wfa96 - jian

17

使用grep命令来匹配起始锚点(^)和结束锚点($)之间没有任何内容的行:

grep -v '^$' infile.txt > outfile.txt

如果你想删除仅包含空格的行,你仍然可以使用grep。在这个例子中,我使用了Perl正则表达式,但还有其他方法:

如果您希望删除只包含空白字符的行,则可以继续使用grep。在本示例中,我使用了Perl正则表达式,但也有其他方法:

grep -P -v '^\s*$' infile.txt > outfile.txt

或者,不使用Perl正则表达式:

grep -v '^[[:space:]]*$' infile.txt > outfile.txt

我的输出文件仍然有空格。 - Teja

12
sed -e '/^ *$/d' input > output

删除所有仅由空格组成(或完全为空)的行。您可以将空格更改为[ \t],其中\t是制表符的表示形式。无论是您的shell还是sed都会执行扩展,但您可能可以直接键入制表符。如果您正在使用GNU或BSD sed,则可以使用-i选项进行就地编辑,如果需要的话。

如果我执行以上命令,我的输出文件仍然有空白行。可能的原因是什么?

可能有几个原因。可能是您没有空白行,但是在行末有很多空格,因此在将文件cat到屏幕时看起来像有空白行。如果是这个问题,那么:
sed -e 's/  *$//' -e '/^ *$/d' input > output

新的正则表达式可以删除行末重复的空格;关于空格或制表符的更多讨论见前文。
另一种可能是你的数据文件来自Windows并带有CRLF换行符。Unix会在行末看到回车符,它不是空格,所以该行不会被删除。有多种方法可以处理这个问题。一种可靠的方法是使用tr命令删除(-d)字符代码八进制15,也称为控制-M或\r或回车符:
tr -d '\015' < input | sed -e 's/  *$//' -e '/^ *$/d' > output

如果以上两种方法都不行,那么您需要展示文件的十六进制转储或八进制转储(od -c)的前两行,这样我们才能看清问题所在。
head -n 2 input | od -c

从您对sed -i不起作用的评论来看,您没有在Linux、Mac OS X或BSD上工作。请问您正在使用哪个平台?(AIX、Solaris、HP-UX可能是相对可信的选择,但还有许多不太可信的选择。)

您可以尝试使用POSIX命名字符类,如sed -e '/^[[:space:]]*$/d';这可能有效,但不能保证。您可以使用以下命令进行尝试:

echo "Hello World" | sed 's/[[:space:]][[:space:]]*/   /'

如果成功的话,“Hello”和“World”之间会有三个空格。如果失败了,你可能会从sed得到一个错误信息。这可以避免在命令行上输入制表符而导致的麻烦。

如果我执行上述命令,但输出文件中仍有空行,可能是什么原因? - Teja
很可能你的“空白”行并不是空的,它们包含了空格。请参考我的答案,以了解如何移除由_任何_空格组成的行。 - Jonathan Wakely
是的,看起来有空格。我该如何删除行末的空格? - Teja
9
哦,真是的,如果你问错了问题,没有人能正确回答! - Jonathan Wakely

8
grep . file

grep会逐行查看您的文件;点号.匹配除换行符以外的任何字符。因此,grep的输出是由所有不仅包含单个换行符的行组成的。


1
如果“空白”行包含空格,则可以使用grep '[^[:space:]]' file - glenn jackman
5
19个字符的解释真的太多吗? - jscs
1
@JoshCaswell 这只是没有意义的。这就像你读到代码上写着“i=0”,然后有人添加了一条注释,“将变量i设置为零”的情况,因为有人告诉他们在代码中添加注释是个好主意。在这种情况下,要么这个grep命令做什么非常明显,要么OP真的需要阅读手册页。 - Ed Morton
2
比起复制粘贴的错误信息说你的帖子太短更没意义?我们对“没意义”有不同的定义。 - jscs
不是更无趣,只是同样无趣而需要更多努力。在完美的世界中,该网站根本不需要规定最少字符数,那么我们也就不必进行这场毫无意义的讨论了。 - Ed Morton

7

with awk

awk 'NF > 0' filename


2
awk 'NF' 单独就足够了。 - fedorqui

3
为了彻底删除行,包括空格或制表符等的内容,可以用perl编写如下代码:
cat file.txt | perl -lane "print if /\S/"

当然还有awk和sed的等效工具。最好不要假设这些行是完全为空的,因为“^$”会执行此操作。
干杯!

2
您可以使用sed的-i选项进行就地编辑,而无需使用临时文件:
 sed -i '/^$/d' file

你能清晰地描述一下,空行仍然存在的确切情况吗? - P.P
我的第19列有空格。所以我想我应该先去掉空格,然后执行任何一个这些命令。 - Teja
不应该删除所有带有任何空格的行,例如<tab>、<space>、<blank line>或这些的任何组合。 - P.P
是的,它与答案中提到的方式相同。 - Teja
你无法避免使用 sed -i 时产生临时文件,因为 sed -i 会使用临时文件。 - William Pursell
显示剩余5条评论

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