Perl Regex:如何从CSV行中删除引号内的引号

时间:2012-05-04 09:54:19

标签: regex perl double-quotes lookahead lookbehind

我从CSV文件中获得一行,其中"作为字段封闭,,作为字段分隔符作为字符串。有时数据中有"会破坏字段封闭程序。我正在寻找正则表达式来删除这些"

我的字符串如下所示:

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

我看过this,但我不明白如何告诉它只删除

的引号
  1. 不在字符串的开头
  2. 不在字符串的末尾
  3. 前面没有,
  4. 后面没有,
  5. 我设法告诉它使用这行代码同时删除3和4:

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

    但是,我无法让^$适合,因为前瞻和后方都不喜欢被写为(?<!(^|,))

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

5 个答案:

答案 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

12表示在逗号之前和之后必须至少有一个字符,因此是正面的结果。 34表示这些字符可以是逗号之外的任何字符。

答案 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。