过滤文本文件以删除空行的好方法是什么?

pit*_*las 11 shell sed awk text-processing

我有一个 .csv 文件(在 Mac 上),它有一堆空行,例如:

"1", "2", "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum 

lorem ipsum ","2","3","4"
"1", "2", "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum 

lorem ipsum ","2","3","4"
Run Code Online (Sandbox Code Playgroud)

我想转换为:

"1", "2", "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum ","2","3","4"
"1", "2", "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum  lorem ipsum ","2","3","4"
Run Code Online (Sandbox Code Playgroud)

我知道必须有一个单行但我不知道 awk 或 sed。任何提示非常感谢!

der*_*ert 11

您可以使用 grep 的-v(反转匹配)模式来执行此操作:

grep -v '^$' old-file.csv > new-file.csv
Run Code Online (Sandbox Code Playgroud)

请注意,由于 shell 重定向的工作方式,这些文件必须是不同的文件。在读取输入文件之前打开(并清空)输出文件。如果您有 moreutils(在 Mac OS X 上不是默认设置),您可以使用它sponge来解决这个问题:

grep -v '^$' file.csv | sponge file.csv
Run Code Online (Sandbox Code Playgroud)

但是,当然,如果出现问题,您将很难返回。

如果您的“空白行”实际上可能包含空格(听起来确实如此),那么您可以改用它:

egrep -v '^[[:space:]]*$' old-file.csv > new-file.csv
Run Code Online (Sandbox Code Playgroud)

这将忽略空行以及仅包含空格的行。您当然可以对其进行相同的sponge转换。


Ont*_*nio 8

最简单的选择就是grep .. 在这里,点表示“匹配任何内容”,因此如果该行为空,则不匹配。否则它会按原样打印整行。


Sté*_*las 6

要删除空行,就地,使用 ksh93:

sed '/./!d' file 1<>; file
Run Code Online (Sandbox Code Playgroud)

所述<>;重定向操作器是专用于ksh93的和是相同的标准<>,除了ksh的截断命令之后的文件已经终止操作。

sed '/./!d'是一种复杂的编写方式grep .,但不幸的是,如果其标准输出指向与其标准输入相同的文件,GNU grep 至少会抱怨。你会说一个人可以写:

grep . file | cat 1<>; file
Run Code Online (Sandbox Code Playgroud)

但不幸的是,ksh93(至少我的版本(93u+))中有一个错误,在这种情况下,文件似乎被截断为零长度。

grep . file | { cat; } 1<>; file
Run Code Online (Sandbox Code Playgroud)

似乎可以解决该错误,但现在,它比 sed 命令复杂得多。


Jos*_* R. 5

这是Perl它的单行:

perl -pi -e 's/^\s*\n//' yourfile
Run Code Online (Sandbox Code Playgroud)

编辑:根据下面 ruakh 的评论改进了代码。


Sté*_*las 5

根据对您的问题的评论中的澄清,例如:

awk -v RS= -v ORS= 1
Run Code Online (Sandbox Code Playgroud)

可以做你想做的。

记录分隔符是一种特殊情况,它告诉awk记录是段落(由空行序列分隔)。将输出记录分隔符设置为空字符串也意味着这些段落的内容(没有分隔符)将被连接起来。1只是打印每条记录的真实条件。

但是,这将省略尾随换行符,因此您可以执行以下操作:

awk -v RS= -v ORS= '1;END{if (NR) printf "\n"}'
Run Code Online (Sandbox Code Playgroud)


pit*_*las 3

我知道如果我提供该文件,事情会更容易,但不幸的是它包含我无法分享的机密信息。与此同时,我写了一个 ruby​​ 脚本,似乎可以解决问题:

require 'csv'
c = CSV.open("outfile1.csv", "w")
CSV.foreach("data.csv", :encoding => 'windows-1251:utf-8') do |row|
  row = row.map { |a| a.class == String ? a.gsub(/\r/, '') : a}
  c << row
end
c.close
Run Code Online (Sandbox Code Playgroud)

感谢大家的帮助!