【问题标题】:CSV parsing, newline/linebreak issuesCSV 解析、换行/换行问题
【发布时间】:2016-02-01 17:10:44
【问题描述】:

我正在尝试为多个 CSV 文件创建解析器,该解析器最终将以 Excel 兼容格式输出到另一个 CSV 文件。 CSV 文件由商业工具导出,该工具采用防火墙配置并向我们报告它发现的任何问题。

到目前为止,我已经弄清楚如何读取文件目录,查找某些值,确定我拥有的设备类型,然后将其输出到屏幕或 CSV,但前提是每行都有单个单元格条目。如果源 IP“单元格”(或任何其他)包含多个 IP,以换行符分隔,则输出会在该换行符处中断并将其余部分推送到下一行。

我目前的代码是:

require 'csv'
require 'pp'

nipperfiles = Dir.glob(ARGV[0] + '/*.csv')

def allcsv(nipperfiles)
  filearray = []
  nipperfiles.each do |csv|
    filearray << csv
  end

  filearray
end

def devicetype(filelist)
  filelist.each do |f|
    CSV.foreach(f, :headers => true, :force_quotes => true) do |row|
      if row["Table"] =~ /audit device list/ && row["Device"] =~ /Cisco/
        return "Cisco"
      elsif row["Table"] =~ /audit device list/ && row["Device"] =~ /Dell/
        return "Sonicwall"
      elsif row["Table"] =~ /audit device list/ && row["Device"] =~ /Juniper/
        return "Juniper"
      end
    end
  end
end

def adminservices(device, filelist)
  administrative = []

  filelist.each do |f|
    CSV.foreach(f, :headers => true, :col_sep => ",", :force_quotes => true, :encoding => Encoding::UTF_8) do |row|
      if row["Table"] =~ /administrative service rule/
        if row["Dst Port"] != "Any" and row["Service"] != "[Host] Any"
          if device == "Cisco"
            administrative << row["Table"] + ',' + row["Rule"] + ',' + row["Protocol"] + ',' + row["Source"] + ',' + row["Destination"] + ',' + row["Dst Port"]
          elsif device == "Sonicwall"
            administrative << row["Table"] + ',' + row["Rule"] + ',' + row["Source"] + ',' + row["Destination"] + ',' + row["Service"]
          elsif device == "Juniper"            
            administrative << row["Table"] + ',' + row["Rule"] + ',' + row["Source"] + ',' + row["Destination"] + ',' + row["Service"]
          end
        end
      end
    end
  end
  administrative
end

def writecsv(admin)

  finalcsv = File.new("randomstorm.csv", "w+")
  finalcsv.puts("Administrative Services Table:\n", admin, "\r\n")
  finalcsv.close

end

filelist = allcsv(nipperfiles)
device = devicetype(filelist)
adminservices(device, filelist)
admin = adminservices(device, filelist)
writecsv(admin)

有没有办法让它忽略单元格内的换行符,或者我的代码是否完整并且需要重新开始?

我尝试使用 CSV 库编写 CSV 文件,但结果相同,我认为这段代码更清楚地说明了问题。

如果有帮助,我可以清理输入文件。

【问题讨论】:

  • 分享几个输入文件中有问题的行的例子
  • 欢迎。请不要使用告别词(“非常感谢”)或签名(“Rich”)。我们正在写一本参考书,而不是进行讨论,所以你正在写一篇关于如何解决你所询问的问题的文章的第一部分。此外,您的代码是演示问题所需的最低限度吗?请阅读“minimal reproducible example”和“How to Ask”。
  • 请提供适用于您的代码并演示问题的最少输入数据。期望我们想象数据效果不佳。广泛使用 CSV 类。 CSV 不是一种易于遵循的格式,并且该类已经过很好的测试,因此它可以处理您未遇到或未想象到的情况。

标签: ruby excel csv


【解决方案1】:

换行符在字段内是可以的,只要它们被引用:

CSV.parse("1,\"2\n\n\",3")
=> [["1", "2\n\n", "3"]]

尝试直接写入documentation 中的字符串或文件,这将确保带换行符的字段被引用:

def writecsv(admin)
 csv_string = CSV.generate do |csv|
   admin.each { |row| csv << row }
 end 

 finalcsv = File.new("randomstorm.csv", "w+")
 finalcsv.puts("Administrative Services Table:\n", csv_string, "\r\n")
 finalcsv.close
end

还要确保将字段写入adminservices() 内的数组:

administrative << [row["Table"], row["Rule"], row["Protocol"], row["Source"], row["Destination"], row["Dst Port"]]

【讨论】:

  • 马丁,非常感谢您的回复!这绝对完美。几天来,我一直在用头撞这堵砖墙。你拯救了我的理智。
  • 使用 File.open 的块形式而不是使用 File.new 是惯用的 Ruby。
猜你喜欢
  • 2020-02-03
  • 2017-07-02
  • 2017-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多