0

假设我要解析文件

$ cat toParse.txt
1 2 3 4 5
1 "2 3" 4 5
1 2" 3" 4 5

前两行很容易解析: Text::CSV可以处理。例如,我试过:

使用严格;
使用文本::CSV;
尽管() {
    咀嚼$_;
    我的 $csv = Text::CSV->new({ sep_char => ' ', quote_char => '"' , binary => 1});
    $csv->解析($_);
    我的@fields = $csv->fields();
    我的 $badArg = $csv->error_input();
    打印“字段[1] = $fields[1]\n”;
    print "错误参数:$badArg\n\n";
}

但是,如果引号字符包含标记化字段中,CSV 会变得非常混乱。

上面的程序打印出来:

字段[1] = 2
不好的论点:

字段[1] = 2 3
不好的论点:

字段[1] =
错误参数:1 2" 3" 4 5

有没有人有什么建议?我希望最后fields[1]填充2" 3 "... 换句话说,我想在引号字符串中不包含的任何空格上拆分行。

4

2 回答 2

1

您想要的不是 CSV,因此您需要编写自己的解析代码。

这应该适用于您的特定情况:

use strict;

while (<DATA>) { 
    chomp $_;
    my @fields = /([^\s"]+|(?:[^\s"]*"[^"]*"[^\s"]*)+)(?:\s|$)/g;
    print "$_\n" for @fields;
    print "\n";
}

__DATA__

1 2 3 4 5
1 "2 3" 4 5
1 2" 3 " 4 5 
1 2" 3 "4 5 
1 2" 3 "4" 5" 6
1 2" 3 "4"" 5"" 6

...它的输出是:

1
2
3
4
5

1
"2 3"
4
5

1
2" 3 "
4
5

1
2" 3 "4
5

1
2" 3 "4" 5"
6

1
2" 3 "4""
5""
6

单击此处进行测试。

于 2012-05-10T22:02:20.253 回答
0

将 quote_char 更改为 " 和第三行将是其他内容

1
2"
3
"
4
5

然而,第二行现在将是

1 
"2
3"
4
5

因此,您似乎有一行,其中 " 是引号分隔符,而另一行则不是。

因此,您正在解析的文件已损坏,您将不得不变得聪明。

于 2012-05-10T21:27:41.197 回答