3

我有一个 CSV 文件中的一行,其中包含字段分隔符",字段分隔符作为字符串。有时",数据中存在破坏字段封闭符的数据。我正在寻找一个正则表达式来删除这些".

我的字符串如下所示:

my $csv = qq~"123456","024003","Stuff","","28" stuff with more stuff","2"," 1.99 ","",""~;

我看过这个,但我不明白如何告诉它只删除引号

  1. 不在字符串的开头
  2. 不在字符串的末尾
  3. 前面没有,
  4. 后面没有,

我设法用这行代码告诉它同时删除 3 和 4 :

$csv =~ s/(?<!,)"(?!,)//g;

但是,我无法将^and$放在那里,因为前瞻和后瞻都不喜欢写成(?<!(^|,)).

除了拆分字符串并从每个元素中删除引号之外,有没有办法仅使用正则表达式来实现这一点?

4

5 回答 5

10

对于操作 CSV 数据,我建议使用Text::CSV - CSV 数据中有很多潜在的复杂性,虽然可以构建代码来处理自己,但当有一个经过试验和测试的 CPAN 模块时,这是不值得的它给你

于 2012-05-04T09:57:10.550 回答
4

不要使用正则表达式来解析 CSV 文件,CPAN 提供了很多好的模块,比如 nickifat 建议的,使用Text::CSV或者你可以使用Text::ParseWords 之类的

use Text::ParseWords;  
while (<DATA>) {
chomp;     
my @f = quotewords ',', 0, $_;     
print join "|" => @f; 
}  

__DATA__ 
"123456","024003","Stuff","",""28" stuff with more stuff","2"," 1.99 ","","" 

输出:

123456|024003|Stuff||28 stuff with more stuff|2| 1.99 || 
于 2012-05-04T10:18:37.870 回答
1

这应该有效:

$csv =~ s/(?<=[^,])"(?=[^,])//g

12暗示逗号前后必须至少有一个字符,因此是积极的环顾四周。34暗示这些字符可以是逗号以外的任何东西。

于 2012-05-04T10:07:03.310 回答
1

感谢您的帮助。我遇到了嵌入双引号的格式错误的 CSV 问题。我会对正则表达式的前瞻部分做一点补充,否则行尾的空值将被破坏:

(?<=[^,])\"(?=[^,\n])

添加 \n 将消除与行尾最后一个双引号的匹配。

于 2013-11-14T00:35:14.407 回答
-1

建议的

$csv =~ s/(?<=[^,])"(?=[^,])//g;

可能是最好的答案。如果没有这些高级正则表达式功能,您也可以使用

$csv =~ s/([^,])"([^,])/$1$2/g;

或者

$csv = join (',', map {s/"//g;"\"$_\""} split (',', $csv));

我认为您应该知道您的字符串格式不正确 csv。在 csv 文件中,值内的双引号必须加倍 (http://en.wikipedia.org/wiki/Comma-separated_values)。使用您的格式,值不能包含逗号附近的引号。

csv 不是那么简单的格式。如果您决定使用“真正的” csv,则应该使用模块。否则,您可能应该删除所有双引号以简化您的代码并澄清您没有使用 csv。

于 2012-05-04T14:32:05.700 回答