【问题标题】:Parsing strings with quote characters inside fields在字段中解析带有引号字符的字符串
【发布时间】:2012-05-10 21:11:43
【问题描述】:

假设我要解析文件

$ 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

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

【问题讨论】:

  • 我想在空格字符" " 上分割每一行,只要空格不包含在带引号的字符串中。
  • 我认为allow_loose_quotes => 1 会做到的。
  • allow_loose_quotes => 1 肯定有帮助,但如果在松散引号内有 sep_char,解析器仍然会中断。
  • “我认为”是因为我不知道在那种情况下会发生什么。呃,好吧。正如有人所说, Text::CSV(_XS) 无论如何都不是正确的工具。而且你手上有一个非常奇怪的格式。
  • 是的,我知道这很奇怪,但不幸的是,我必须一直处理看起来像这样的东西;数据并不总是巧妙地构造:) 我总是使用正则表达式来处理它,但我想我希望有一个更清洁的解决方案。

标签: perl csv tokenize


【解决方案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进行测试。

【讨论】:

  • 谢谢。我一直在使用 reg-ex 来解析(坏)看起来像这样的数据,我想我想知道是否有更清洁的方法来做到这一点。
【解决方案2】:

将 quote_char 更改为 " 和第三行将是

1
2"
3
"
4
5

但是现在第二行将是

1 
"2
3"
4
5

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

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

【讨论】:

  • 我想对所有三行都使用 " 引号分隔符,这将使我想要的输出分别看起来像:fields[1] = 2fields[1] = 2 3fields[1] = 2" 3 "
  • Eh 2" 3 " 没有发生想象如果字段分隔符是逗号
  • 为了说明您导致解析器的困难。使用引号分隔符 ' Then 1 '2 3' 4 和 1 '2" 3 "' 4 会起作用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多