正则表达式以匹配CSV分隔符

kpe*_*nka 9 regex

我正在尝试创建一个PCRE,它只匹配CSV文件中一行中用作分隔符的逗号.假设一行的格式是这样的:

1,"abcd",2,"de,fg",3,"hijk"
Run Code Online (Sandbox Code Playgroud)

我希望匹配所有逗号,除了'e'和'f'之间的逗号.或者,如果这是更容易或更明智的解决方案,那么仅匹配那个是可接受的.我有一种感觉,我需要使用负前瞻断言来处理这个问题,但我发现它有点太难以弄明白了.

age*_*t-j 9

有关更多详细信息,请参阅我的帖子以解决此问题.

^(?:(?:"((?:""|[^"])+)"|([^,]*))(?:$|,))+$将匹配整行,然后你可以使用match.Groups [1] .Captures来获取你的数据(没有引号).此外,我让"我的名字是""在引号"""是一个有效的字符串.


And*_*ter 6

CSV解析是一个难题,并且已经很好地解决了.无论你使用什么语言都无疑有一个完整的解决方案来处理它,而你不必走在写自己的正则表达式的道路上.

你用的是哪种语言?


Jon*_*ler 5

正如你已经被告知的那样,正则表达式真的不合适; 处理一般情况是很棘手的(如果在字段中允许换行则加倍,如果你可能不得不处理格式错误的CSV数据,则会三倍.

  • 我建议使用CSVFIX工具来做你需要的.

要查看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是正确的.此外,从字段中提取两个双引号""""并不是您想要的最终结果; 你必须对字段进行后处理,以消除每对相邻双引号中的一个.