【问题标题】:How to build a regular expression to parse comma separated values but ignore the comma with in the double quotes?如何构建正则表达式来解析逗号分隔值但忽略双引号中的逗号?
【发布时间】:2011-07-13 00:19:42
【问题描述】:

示例字符串:

2011-03-09,4919 1281 0410 9930,55107,SAZB2314,"John, Doe" ,1-888-888-4452 ext 1813

需要标记所有逗号,但不是双引号内的逗号。

【问题讨论】:

  • 不要使用正则表达式。不要使用正则表达式。不要使用正则表达式。使用文本解析器。
  • 但是文本解析器不使用正则表达式将输入分解为标记吗?
  • 如果您想学习,请不要使用文本解析器。如果您想提高工作效率,请不要使用正则表达式。

标签: regex perl unix expression


【解决方案1】:

您可以使用 CPAN 中的 Text::CSV

【讨论】:

    【解决方案2】:

    如果您需要一个正则表达式而不是像@eugene y 建议的适当的解析器,这里是一种尝试。捕获应按顺序返回列表元素。

    (?:(?:([^"]*?|".*?"),)*([^"]*?|".*?"))?
    

    【讨论】:

      【解决方案3】:

      或者使用Text::CSV_XS,它做同样的事情但速度更快。

      【讨论】:

      • 它不一定更快,因为 Text::CSV 会导致使用 Text::CSV_XS(如果可用)。不过,我确实建议使用 Text::CSV_XS,因为它也消除了使用 Text::CSV 的额外复杂性,并且可以保证在较慢的 Text::CSV_PP 上获得 Text::CSV_XS。
      【解决方案4】:

      使用Data::Record

      【讨论】:

        【解决方案5】:

        试试:

        use strict;
        use warnings;
        use Text::ParseWords;
        
        while (<DATA>) {
            chomp;
            my @f = quotewords ',', 0, $_;
            for (@f) {
                    s/^\s*|\s*$//g;
                    s/^/"/ && s/$/"/ if /,/;
            }
            print join (",", @f), "\n";
        }
        
        __DATA__
        2011-03-09,4919 1281 0410 9930,55107,SAZB2314,"John, Doe" ,1-888-888-4452 ext 1813
        "ashish", "kumar", "test,1", "test2"
        "foo", "b,ar", "msg1", "msg2"
        

        【讨论】:

          【解决方案6】:

          我知道如何在 Java 中做到这一点。正则表达式在 PERL 中的工作方式可能不同,但让我展示一下这个想法。有3个子句的并集。

          // 1) select any quoted text before comma
          // if it fails then
          // 2) select any text before comma
          // if it also fails then
          // 3) select any text before end of the input
          
          final String OR           = "|";
          final String QUOTE        = "\"[\\s]*"; //with trailing whitespaces
          final String NON_QUOTES   = "[^\"]*";
          final String COMMA        = ",";
          final String NON_COMMA    = "[^,]*"; 
          final String NON_END      = "[^$]+"; 
          final String END          = "$";
          
          final Pattern p = Pattern.compile(
          QUOTE+NON_QUOTES+QUOTE+COMMA+
          OR+
          NON_COMMA+COMMA+
          OR+
          NON_END+END);
          

          它将为您提供不幸地以逗号结尾的匹配项,最后一个除外。没有捕获组,因为像这样用 union 子句定义它们没有意义。

          【讨论】:

          • Regexp::Grammars、Parser::MGC 或 Parse::RecDescent 之类的东西将是创建与此等效的 Perl 代码的方法。但是对于 CSV,已经有模块可以解决这个问题。
          【解决方案7】:

          我目前正在做一个项目,这个正则表达式帮助我获得了完全相同格式的 csv 文件。

          ("([^"]*)",?)|(([^",]*),?)

          如果一条记录被随机分成多行,这将不起作用。我遇到了这个问题,并通过确定非空匹配的计数是否正确来解决它。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-11-25
            • 2013-07-30
            • 2021-08-24
            • 2014-02-26
            • 1970-01-01
            相关资源
            最近更新 更多