【问题标题】:Regex to select semicolons that are not enclosed in double quotes正则表达式选择不包含在双引号中的分号
【发布时间】:2013-06-26 22:49:00
【问题描述】:

我有类似的字符串

a;b;"aaa;;;bccc";deef

我想根据分隔符 ; 拆分字符串,前提是 ; 不在双引号内。所以分裂之后就是

 a
 b
"aaa;;;bccc"
 deef

我尝试使用look-behind,但找不到正确的正则表达式进行拆分。

【问题讨论】:

  • 1.你真的需要使用正则表达式吗?这不是一个好的工具;状态机会更好。 2. 你基本上是在做 CSV 解析,但是用分号而不是逗号。您是否寻找过允许您使用不同分隔符的 CSV 库?

标签: regex


【解决方案1】:

正则表达式可能不是解决此问题的正确工具。如果可能的话,您应该使用 CSV 库,指定 ; 作为分隔符并指定 " 作为引号字符,这应该会为您提供您正在寻找的确切字段。

这里要说的是一种方法,它通过确保在我们正在考虑拆分的; 和字符串的结尾之间有偶数个引号来工作。

;(?=(([^"]*"){2})*[^"]*$)

示例:http://www.rubular.com/r/RyLQyR8F19

如果您可以在字符串中使用转义引号,例如a;"foo\"bar";c,这将被打破。

这是一个使用 Python 的 csv module 的更简洁的示例:

import csv, StringIO
reader = csv.reader(StringIO.StringIO('a;b;"aaa;;;bccc";deef'),
                    delimiter=';', quotechar='"')
for row in reader:
    print '\n'.join(row)

【讨论】:

  • 但是匹配所有会比拆分简单得多:"[^"]*"|[^";]+
【解决方案2】:

这有点难看,但如果你在引用的字符串中没有 \" (意味着你没有看起来像这样的字符串 ("foo bar \"badoo\" goo") 你可以拆分" 首先,然后假设所有偶数数组元素实际上都是字符串(并将奇数元素拆分为 ; 标记上的组成部分)。

如果您的字符串中*确实有 \",那么您需要先将它们转换为其他临时令牌,稍后您将在执行操作后将其转换回来。

这是一个小提琴......

http://jsfiddle.net/VW9an/

    var str = 'abc;def;ghi"some other dogs say \\"bow; wow; wow\\". yes they do!"and another; and a fifth'

var strCp = str.replace(/\\"/g,"--##--");

var parts = strCp.split(/"/);

var allPieces = new Array();
for(var i in parts){
    if(i % 2 == 0){
        var innerParts = parts[i].split(/\;/)
        for(var j in innerParts)
            allPieces.push(innerParts[j])
    }
    else{
        allPieces.push('"' + parts[i] +'"')
    }
}

for(var a in allPieces){
 allPieces[a] = allPieces[a].replace(/--##--/g,'\\"');   
}

console.log(allPieces)

【讨论】:

    【解决方案3】:

    正则表达式只会变得更混乱,即使是很小的变化也会中断。您最好使用带有任何脚本语言的csv 解析器。 Perl 内置模块(如果有任何限制,则无需从 CPAN 下载)称为 Text::ParseWords 允许您指定分隔符,以便您不限于 ,。这是一个示例 sn-p:

    #!/usr/local/bin/perl
    
    use strict;
    use warnings;
    
    use Text::ParseWords;
    
    my $string = 'a;b;"aaa;;;bccc";deef';
    my @ary = parse_line(q{;}, 0, $string);
    
    print "$_\n" for @ary;
    

    输出

    a
    b
    aaa;;;bccc
    deef
    

    【讨论】:

    • 对于php,有str_getcsv
    • 感谢@AlainTiemblo 的建议。不确定 OP 使用哪种脚本语言很舒服,所以这肯定会有所帮助! :)
    【解决方案4】:

    匹配所有而不是拆分

    在战斗后很久才回答,因为没有人使用我认为最简单的方式。

    一旦你理解了Match All and Split are Two Sides of the Same Coin,你就可以使用这个简单的正则表达式:

    "[^"]*"|[^";]+
    

    查看Regex Demo中的匹配项。

    • 交替的左侧| 匹配完整的引号字符串
    • 右侧匹配任何既不是; 也不是" 的字符

    【讨论】:

      猜你喜欢
      • 2012-04-06
      • 2019-01-02
      • 1970-01-01
      • 1970-01-01
      • 2015-06-13
      • 2013-05-10
      • 1970-01-01
      • 2011-09-15
      • 2014-07-27
      相关资源
      最近更新 更多