Sai*_*Sai 15 ruby regex csv fastercsv
我正在处理政府来源(FEC,州选民数据库等)的数据.它的格式不一致,这会以各种令人愉快的方式破坏我的CSV解析器.
它是外部采购和权威的.我必须解析它,我不能重新输入,在输入时验证等.就是这样; 我不控制输入.
属性:
Foo \xAB bar)"foo",123,"bar")或不带引号(foo,123,bar).我还没有遇到任何在给定行(即"foo",123,bar)中混合的地方,但它可能在那里.我正在使用Ruby FasterCSV(在1.9中仅称为CSV),但这个问题应该与语言无关.
我的猜测是,解决方案需要使用明确的记录分隔符/引号字符(例如ASCII RS,STX)进行预处理替换.我已经在这里开始了一点但它并不适用于我得到的一切.
如何可靠地处理这种脏数据?
ETA:以下是单个文件中可能包含的简化示例:
"this","is",123,"a","normal","line" "line","with "an" internal","quote" "short line","with an "internal quote", 1 comma and linebreaks" un "quot" ed,text,with,1,2,3,numbers "quoted","number","series","1,2,3" "invalid \xAB utf-8"
在将CSV文件传递给Ruby的CSV解析器之前,可以将Ruby的文件子类化为处理CSV文件的每一行.例如,以下是我使用此技巧用标准双引号替换非标准反斜杠转义引号""
class MyFile < File
def gets(*args)
line = super
if line != nil
line.gsub!('\\"','""') # fix the \" that would otherwise cause a parse error
end
line
end
end
infile = MyFile.open(filename)
incsv = CSV.new(infile)
while row = incsv.shift
# process each row here
end
Run Code Online (Sandbox Code Playgroud)
原则上你可以进行各种额外的处理,例如UTF-8清理.这种方法的好处是您可以逐行处理文件,因此您无需将其全部加载到内存中或创建中间文件.
首先,这是一个相当幼稚的尝试:http://rubular.com/r/gvh3BJaNTc
/"(.*?)"(?=[\r\n,]|$)|([^,"\s].*?)(?=[\r\n,]|$)/m
Run Code Online (Sandbox Code Playgroud)
这里的假设是:
这几乎可以满足您的要求,但在这些字段上失败:
1 个逗号和 换行符”
正如TC 在评论中指出的那样,您的文字不明确。我相信您已经知道了,但为了完整起见:
"a"- 那是a还是"a"?如何表示想要用引号引起来的值?"1","2"- 可能被解析为1、2或 as 1","2- 两者都是合法的。,1 \n 2,- 值中的行尾或换行符?您无法判断,特别是这是否应该是其行的最后一个值。1 \n 2 \n 3- 一个带有换行符的值?两个值(1\n2、3或1、2\n3)?三个值?如果检查每行的第一个值,您可能会得到一些线索,正如您所说,它应该告诉您列数及其类型 - 这可以为您提供解析文件时缺少的附加信息(例如,如果您知道该行中应该有另一个字段,那么所有换行符都属于当前值)。即便如此,看起来这里还是存在严重的问题......