繁体   English   中英

更智能的 CSV 忽略 csv 中的空行

[英]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 

示例文件:

[测试.csv[1]

输出

在此处输入图片说明

让我们首先构建您的文件。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM