[英]Smarter CSV ignore blank lines in csv
我正在使用 Smarter CSV 并且遇到了一个带有空行的 csv。 反正有没有忽略这些? 更智能的 CSV 将空行作为标题,而不是正确处理文件。 有什么办法可以让comment_regexp混蛋吗?
mail.attachments.each do | attachment |
filename = attachment.filename
#filedata = attachment.decoded
puts filename
begin
tmp = Tempfile.new(filename)
tmp.write attachment.decoded
tmp.close
puts tmp.path
f = File.open(tmp.path, "r:bom|utf-8")
options = {
:comment_regexp => /^#/
}
data = SmarterCSV.process(f, options)
f.close
puts data
示例文件:
[
输出
让我们首先构建您的文件。
str = <<~_
#
# Report
#---------------
Date header1 header2 header3 header4
20200 jdk;df 4543 $8333 4387
20200 jdk 5004 $945876 67
_
fin_name = 'in'
File.write(fin_name, str)
#=> 223
使用SmarterCSV::process方法读取此文件必须解决两个问题。 第一个是注释——以八字 ( '#'
) 开头的行——和空行必须被跳过。 第二个是字段分隔符不是固定长度的字符串。
这些问题中的第一个可以通过将process
' :comment_regexp
选项键的值设置为正则表达式来处理:
:comment_regexp => /\A#|\A\s*\z/
其内容为:“匹配字符串开头的 octothorpe( \\A
是字符串开头的锚点)或 ( |
) 匹配包含零个或多个空白字符的字符串( \\s
是空白字符, \\z
是字符串结尾锚点)”。
不幸的是, SmarterCSV
不能处理可变长度的字段分隔符。 它确实有一个选项:col_sep
,但它的值必须是一个字符串,而不是一个正则表达式。
因此,我们必须在使用SmarterCSV
之前对文件进行SmarterCSV
,但这并不困难。 虽然都在,我们不妨删除美元符号并使用逗号作为字段分隔符。 1
fout_name = 'out.csv'
fout = File.new(fout_name, 'w')
File.foreach(fin_name) do |line|
fout.puts(line.strip.gsub(/\s+\$?/, ',')) unless
line.match?(/\A#|\A\s*\z/)
end
fout.close
让我们看看生成的文件。
puts File.read(fout_name)
显示
Date,header1,header2,header3,header4
20200,jdk;df,4543,8333,4387
20200,jdk,5004,945876,67
现在这就是 CSV 文件的样子! 我们现在可以在这个文件上使用SmarterCSV
而不指定任何选项:
SmarterCSV.process(fout_name)
#=> [{:date=>20200, :header1=>"jdk;df", :header2=>4543,
# :header3=>8333, :header4=>4387},
# {:date=>20200, :header1=>"jdk", :header2=>5004,
# :header3=>945876, :header4=>67}]
1. 我使用IO::foreach逐行读取文件,然后将每一行既不是注释也不是空行的操作写入输出文件。 如果文件不是很大,我们可以改为吞掉它变成一个字符串,修改字符串,然后写结果字符串输出文件: File.write(fout_name, File.read(fin_name).gsub(/^#.*?\\n|^[ \\t]*\\n|^[ \\t]+|[ \\t]+$|\\$/, '').gsub(/[ \\t]+/, ','))
。 第一个正则表达式读取,“匹配以八字形开头的行或仅包含空格和制表符的行,或行首的空格和制表符或行尾的空格和制表符或美元符号”。 第二个gsub
只是将多个制表符和空格转换为逗号。
File.new(fout_name, 'w') File.foreach(fin_name) do |line| fout.puts(line.strip.gsub(/\\s+\\$?/, ',')) 除非 line.match?(/\\A#|\\A\\s*\\z/) 结束 fout.close
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.