Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ssis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Regex 匹配CSV分隔符的正则表达式_Regex - Fatal编程技术网

Regex 匹配CSV分隔符的正则表达式

Regex 匹配CSV分隔符的正则表达式,regex,Regex,我正在尝试创建一个PCRE,它将只匹配CSV文件中用作行分隔符的逗号。假设行的格式如下所示: 1,"abcd",2,"de,fg",3,"hijk" 我想匹配除“e”和“f”之间的逗号以外的所有逗号。或者,如果这是一个更容易或更明智的解决方案,那么只匹配一个是可以接受的。我有一种感觉,我需要使用一个否定的前瞻性断言来处理这个问题,但我发现这有点太难了。如果不认真思考,我会做一些类似于[0-9]+|“[^”]*”的事情来匹配除逗号分隔符以外的所有内容。这会奏效吗 如果没有上下文,就不可能给出更具

我正在尝试创建一个PCRE,它将只匹配CSV文件中用作行分隔符的逗号。假设行的格式如下所示:

1,"abcd",2,"de,fg",3,"hijk"

我想匹配除“e”和“f”之间的逗号以外的所有逗号。或者,如果这是一个更容易或更明智的解决方案,那么只匹配一个是可以接受的。我有一种感觉,我需要使用一个否定的前瞻性断言来处理这个问题,但我发现这有点太难了。

如果不认真思考,我会做一些类似于
[0-9]+|“[^”]*”
的事情来匹配除逗号分隔符以外的所有内容。这会奏效吗


如果没有上下文,就不可能给出更具体的解决方案。

CSV解析是一个困难的问题,已经得到了很好的解决。毫无疑问,无论您使用什么语言,都有一个完整的解决方案来处理它,而无需编写自己的正则表达式

您使用的是什么语言?

有关详细信息,请参阅我的


^((?:“(?:”)+)“(?:”[^,]*)(?:$)+$
将匹配整行,然后您可以使用match.Groups[1]。捕获以获取数据(不带引号)。另外,我让“我的名字是”“在引号中”“是一个有效的字符串。

正如你已经被告知的,正则表达式是不合适的;处理一般情况是很棘手的(如果字段中允许换行,则加倍如此,如果您可能必须处理格式错误的CSV数据,则加倍如此)

  • 我建议该工具尽可能满足您的需要

看看CSV有多坏,考虑这个数据(有5个干净的字段,其中两个是空的):

注意,第一个字段只包含一个双引号。将两个双引号压扁为一个非常困难;在用正则表达式捕获两个引文之后,可能需要用第二遍来做。

"",,"",a",b c",
问题是以
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;
    }
}
使用严格;
使用警告;
我的@list=(q{“”,,a,“a,b”},q{“”,“,a”,bc”,});
foreach my$string(@list)
{
打印“图案:\n”;
而($string=~m/(?:”((?:“”[^])*)“((?:“”[^,][^,]*)|(.?))
(?:$|,)/gx)
{
如果定义为$1,则打印“发现QF:\n”;
如果定义为$2,则打印“发现PF:\n”;
如果定义为$3,则打印“Found EF:\n”;
}
}
请注意,如前所述,您必须确定实际使用了三个捕获中的哪一个。通过两个阶段的处理,您可以只处理一个捕获,然后去掉封闭的双引号和嵌套的双引号。此正则表达式假定,如果字段不以双引号开头,则双引号没有特殊含义我的意思是在球场内。祝你玩得开心

输出:

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: <<>>
模式:
成立资历架构:
找到EF:
成立资历架构:
找到PF:
成立资历架构:
找到EF:
模式:
成立资历架构:
找到EF:
成立资历架构:
找到PF:>
找到EF:
我们可以讨论第一个模式末尾的空字段(EF)是否正确;它可能不正确,这就是为什么我说“非常接近”。哦,第二个模式末尾的EF是正确的。
另外,从字段
中提取两个双引号
不是您想要的最终结果;您必须对字段进行后期处理,以消除每一对相邻的双引号中的一个。

安迪的观点:正确解析CSV比您可能意识到的要困难得多,并且有各种各样难看的边缘情况。我怀疑从数学上讲,用正则表达式正确解析CSV是不可能的,尤其是只有sed所理解的人才能理解

使用使用的Perl脚本(或首选脚本语言中的等效脚本)而不是sed

use Text::CSV;
use feature 'say';

my $csv = Text::CSV->new ( { binary => 1, eol => $/ } )
    or die "Cannot use CSV: ".Text::CSV->error_diag ();
my $rows = $csv->getline_all(STDIN);
for my $row (@$rows) {
    say join("\t", @$row);
}

当然,这假设您的数据中没有任何制表符-也许最好也使用真正的脚本语言执行后续阶段,这样您就可以利用适当的列表了?

我知道这很旧,但这个正则表达式对我来说很有用:

/(\"[^\"]+\")|[^,]+/g
它可能用于任何语言。我用JavaScript测试了它,所以g只是一个全局修饰符。它甚至可以用于混乱的行(额外的引号),但不能处理空


只是分享,也许这会对某人有所帮助。

不,因为这与“e”和“f”之间的逗号不匹配,即使这不是分隔符。我应该更清楚一点——在这种情况下,双引号之间的逗号不被视为分隔符。此外,我给出的格式并不意味着每一行看起来都是精确的同样,但是一行由数字和双引号字符串组成,用逗号分隔。如果我不清楚,很抱歉;如果没有更多信息,很难知道您的用例。通常,当有人解析CSV时,他们真正想要的是值,而不是分隔符。带有此正则表达式的MatchAll类型函数会给您一个list/CSV文件中所有项目的数组。如果,如您在另一条评论中所说,您正在使用
sed
将逗号更改为其他内容,为什么不使用
grep-eo
来获取换行符分隔的值?出于好奇,为什么要匹配逗号?您试图实现什么?我建议完全避免使用regex来解决此问题-以及采用在所有逗号上拆分字符串的方法,然后通过拆分的组件合并以引号开头/结尾的组件(在过程中删除引号)。虽然这在一句话中有点过于简单,但仍然是一个simp
/(\"[^\"]+\")|[^,]+/g