我从CSV文件中获得一行,其中"
作为字段封闭,,
作为字段分隔符作为字符串。有时数据中有"
会破坏字段封闭程序。我正在寻找正则表达式来删除这些"
。
我的字符串如下所示:
my $csv = qq~"123456","024003","Stuff","","28" stuff with more stuff","2"," 1.99 ","",""~;
我看过this,但我不明白如何告诉它只删除
的引号,
,
我设法告诉它使用这行代码同时删除3和4:
$csv =~ s/(?<!,)"(?!,)//g;
但是,我无法让^
和$
适合,因为前瞻和后方都不喜欢被写为(?<!(^|,))
。
除了拆分字符串并从每个元素中删除引用之外,有没有办法只使用正则表达式来实现这一点?
答案 0 :(得分:10)
对于操纵CSV数据,我建议使用Text::CSV - CSV数据中存在很多潜在的复杂性,虽然可以构建代码来处理自己,但是当经过试验和测试时,这是不值得的。 CPAN模块为您完成
答案 1 :(得分:4)
不要使用 Regex 来解析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 ||
答案 2 :(得分:1)
这应该有效:
$csv =~ s/(?<=[^,])"(?=[^,])//g
1
和2
表示在逗号之前和之后必须至少有一个字符,因此是正面的结果。 3
和4
表示这些字符可以是逗号之外的任何字符。
答案 3 :(得分:0)
感谢您的帮助。我遇到了带有嵌入式双引号的格式错误的CSV的问题。我会对正则表达式的前瞻部分做一点补充,否则行末尾的空值将被破坏:
(?<=[^,])\"(?=[^,\n])
添加\ n将消除与行尾的最后一个双引号的匹配。
答案 4 :(得分:-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。