我正在尝试创建一个PCRE,它只匹配CSV文件中一行中用作分隔符的逗号.假设一行的格式是这样的:
1,"abcd",2,"de,fg",3,"hijk"
Run Code Online (Sandbox Code Playgroud)
我希望匹配所有逗号,除了'e'和'f'之间的逗号.或者,如果这是更容易或更明智的解决方案,那么仅匹配那个是可接受的.我有一种感觉,我需要使用负前瞻断言来处理这个问题,但我发现它有点太难以弄明白了.
正如你已经被告知的那样,正则表达式真的不合适; 处理一般情况是很棘手的(如果在字段中允许换行则加倍,如果你可能不得不处理格式错误的CSV数据,则会三倍.
要查看CSV有多糟糕,请考虑此数据(包含5个干净字段,其中两个为空):
"""",,"",a,"a,b"
Run Code Online (Sandbox Code Playgroud)
请注意,第一个字段只包含一个双引号.将两个双引号压缩成一个是非常艰难的; 在使用正则表达式捕获两者之后,你可能必须使用第二遍.并考虑这个格式错误的数据:
"",,"",a",b c",
Run Code Online (Sandbox Code Playgroud)
问题在于,以字母开头的字段a包含双引号; 怎么解释呢?停在逗号?然后,开头的字段b同样是不正确的.停在下一个报价?所以这个领域是a",b c"(或者应该删除引号)?等等......呸!
这个Perl非常接近正确处理上述数据行和可怕的正则表达式:
use strict;
use warnings;
my @list = ( q{"""",,"",a,"a,b"}, q{"",,"",a",b c",} );
foreach my $string (@list)
{
print "Pattern: <<$string>>\n";
while ($string =~ m/ (?: " ( (?:""|[^"])* ) " | ( [^,"] [^,]* ) | ( .? ) )
(?: $ | , ) /gx)
{
print "Found QF: <<$1>>\n" if defined $1;
print "Found PF: <<$2>>\n" if defined $2;
print "Found EF: <<$3>>\n" if defined $3;
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,如上所述,您必须确定实际使用的三个捕获中的哪一个.通过两个阶段处理,您可以处理一个捕获,然后删除封闭的双引号和嵌套的双引号双引号.这个正则表达式假定如果该字段不以双引号开头,那么双引号在该字段中没有特殊含义.玩得开心响应!
输出:
Pattern: <<"""",,"",a,"a,b">>
Found QF: <<"">>
Found EF: <<>>
Found QF: <<>>
Found PF: <<a>>
Found QF: <<a,b>>
Found EF: <<>>
Pattern: <<"",,"",a",b c",>>
Found QF: <<>>
Found EF: <<>>
Found QF: <<>>
Found PF: <<a">>
Found PF: <<b c">>
Found EF: <<>>
Run Code Online (Sandbox Code Playgroud)
我们可以讨论第一个模式结束时的空场(EF)是否正确; 它可能不是,这就是为什么我说'非常接近'.OTOH,第二种模式结束时的EF是正确的.此外,从字段中提取两个双引号""""并不是您想要的最终结果; 你必须对字段进行后处理,以消除每对相邻双引号中的一个.
| 归档时间: |
|
| 查看次数: |
22326 次 |
| 最近记录: |