如何解析PERL中包含字段中的引号的CSV?

时间:2015-11-12 02:46:01

标签: perl csv

我的数据中有引号,引用地址中属性的名称。例如

"21JAN1984:00:00:00","M",""Millfield""," "

PERL Text :: CSV此时因错误而死亡

CSV_PP ERROR: 2025 - EIQ - Loose unescaped escape

这对我来说就像有效的CSV,就像一个字段,“詹姆斯说”很好“。”。

使用的代码的缩写版本是:

my $csv = Text::CSV->new({
  binary => 1,
  auto_diag => 1,
  eol => "\n",
  always_quote => 1
}) or die "Cannot use CSV: " . Text::CSV->error_diag();

open my $fh, '<',  $ARGV[0] or die $!;
while (my $person = $csv->getline_hr($fh)) {
  ...
}

1 个答案:

答案 0 :(得分:5)

解决修订后的问题

"21JAN1984:00:00:00","M",""Millfield""," "

如果您想要Millfield之前的双引号和其后的双引号,则正确的CSV格式为:

"21JAN1984:00:00:00","M","""Millfield"""," "

如上所述,CSV数据已损坏。或者,无论如何,它不是&#39;标准&#39;格式。您可以在RFC4180找到CSV的标准规范。这与Microsoft的规范不同; RFC本身确定Excel并没有精确地使用这种格式。

由于您使用的是Perl的Text::CSV模块,因此您应该阅读其规范。请注意, allow_loose_quotes 属性描述的输入与您尝试处理的内容完全相同。它是可用于在Text::CSV方法中配置new行为的众多属性之一。

解决原始问题

问题的原始版本中显示的是非常错误的CSV格式。

21JAN1984:00:00:00","M",""Millfield""," "

00之后的双引号在格式中没有位置。充其量,您必须将其视为由后面的逗号分隔的字段末尾的常规字符。 "M"没有争议。 ""Millfield""格式不正确;如果一个字符串以双引号开头,它将在下一个双引号结束,除非它本身后跟另一个双引号,所以第二个双引号是错误的。如果字段以双引号开头,则应用双引号括起来。您可以做的最好的事情是假设该字段为Millfield""并停在逗号处,但任何正常规则都是错误的。根据这些错误恢复规则,最后的" "是无争议的。

为了使形式合理且包含"Millfield"作为价值,您需要以下其中一项:

"21JAN1984:00:00:00","M","""Millfield"""," "
21JAN1984:00:00:00,"M","""Millfield"""," "
21JAN1984:00:00:00,M,"""Millfield"""," "
21JAN1984:00:00:00,M,"""Millfield""", 

这些行中的最后一行有一个尾随空白。

或者,如果Millfield在提取时不应被双引号括起来,那么所有双引号都是多余的,尽管任何字段都可以被一对双引号括起来。