在字段内解析带引号字符的字符串

时间:2012-05-10 21:11:43

标签: perl csv tokenize

假设我要解析文件

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

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

use strict; 
use Text::CSV; 
while() { 
    chomp $_; 
    my $csv = Text::CSV->new({ sep_char => ' ', quote_char => '"' , binary => 1});
    $csv->parse($_); 
    my @fields = $csv->fields(); 
    my $badArg = $csv->error_input(); 
    print "fields[1] = $fields[1]\n"; 
    print "Bad argument: $badArg\n\n"; 
}

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

以上程序打印出来:

fields[1] = 2
Bad argument:

fields[1] = 2 3
Bad argument:

fields[1] =
Bad argument: 1 2" 3 " 4 5

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

2 个答案:

答案 0 :(得分: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

点击here进行测试。

答案 1 :(得分:0)

将quote_char改为其他“和第三行

1
2"
3
"
4
5

然而,第二行现在将是

1 
"2
3"
4
5

所以你似乎有一行“是引号分隔符而另一行不是。

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