使用Text :: CSV在perl中解析CSV文件时出现问题

src*_*ulo 2 csv perl parsing

我正在尝试使用Text :: CSV解析此CSV文件。这是我的做法:

open my $fh, '<', 'test.csv' or die "can't open csv";
my $csv = Text::CSV_XS->new ({ sep_char => "\t", binary => 1 , eol=> "\n"});
$csv->column_names($csv->getline($fh));

while(my $row = $csv->getline_hr($fh)) {
    # use row
}
Run Code Online (Sandbox Code Playgroud)

因为该文件有169,252行(不计算标题行),所以我希望循环可以运行多次。但是,它只运行8次,并给我8行。我不确定发生了什么,因为CSV看起来像是带有\n行分隔符和\t字段分隔符的普通CSV文件。如果我像这样遍历文件:

while(my $line = <$fh>) {
    my $fields = $csv->parse($line);
}
Run Code Online (Sandbox Code Playgroud)

然后循环遍历所有行。

Dra*_*oan 5

Text :: CSV_XS静默失败,并显示错误。如果将以下内容放在while循环之后:

 my ($cde, $str, $pos) = $csv->error_diag ();
 print "$cde, $str, $pos\n";
Run Code Online (Sandbox Code Playgroud)

您可以查看是否存在解析文件的错误并获得输出:

2034, EIF - Loose unescaped quote, 336
Run Code Online (Sandbox Code Playgroud)

这意味着该列:

GT New Coupe 5.0L CD Wheels: 18" x 8" Magnetic Painted/Machined 6 Speakers
Run Code Online (Sandbox Code Playgroud)

有一个未引用的转义字符串(“之前没有反斜杠)。

Text::CSV的perldoc状态:

allow_loose_quotes

默认情况下,解析未引用字段中包含quote_char字符的字段,例如

1,foo "bar" baz,42
Run Code Online (Sandbox Code Playgroud)

会导致解析错误。尽管允许这种格式仍然是不好的做法,但我们不能帮助有些供应商使他们的应用程序吐出这种样式的行。

如果将参数更改为创建Text::CSV_XS到:

my $csv = Text::CSV_XS->new ({ sep_char => "\t", binary => 1,
    eol=> "\n", allow_loose_quotes => 1 });
Run Code Online (Sandbox Code Playgroud)

问题消失了,直到105265行,错误2023抬起头:

2023, EIQ - QUO character not allowed, 406
Run Code Online (Sandbox Code Playgroud)

perldoc中此错误的详细信息:

2023年“ EIQ-不允许使用QUO字符”

诸如“ foo” bar“ baz”,qu和2023,“,2008-04-05,” Foo,Bar“,\ n之类的序列会导致此错误。

将引号字符设置为空(quote_char => ''在上调用进行设置Text::CSV_XS->new())似乎可以解决此问题,并允许处理整个文件。但是,我将花费一些时间来检查这是否是CSV数据的明智选择。

TL; DR 总而言之,就是您的CSV格式不是最佳格式,因此您必须解决它。