【问题标题】:Matching items in a comma-delimited list which aren't surrounded by single or double quotes匹配逗号分隔列表中未被单引号或双引号包围的项目
【发布时间】:2016-03-14 14:13:01
【问题描述】:

我想匹配逗号分隔列表中的任何文本实例。为此,以下正则表达式效果很好:

/[^,]+/g

(Regex101 demo).

问题是我想忽略包含在单引号或双引号中的任何逗号,我不确定如何扩展上述选择器以允许我这样做。

这是一个示例字符串:

abcd, efgh, ij"k,l", mnop, 'q,rs't

我想要匹配五个文本块匹配四个相关的逗号(这样我就可以使用split() 而不是match() 检索数据):

  1. abcd
  2. efgh
  3. ij"k,l"
  4. mnop
  5. 'q,rs't

或者:

abcd, efgh, ij"k,l", mnop, 'q,rs't
    ^     ^        ^     ^

我该怎么做?


存在三个相关问题,但它们都不能同时满足 JavaScript 中的 '"

  1. Regex for splitting a string using space when not surrounded by single or double quotes - Java 解决方案,似乎不适用于 JavaScript。
  2. A regex to match a comma that isn't surrounded by quotes - 仅匹配 "
  3. Alternative to regex: match all instances not inside quotes - 仅匹配 "

【问题讨论】:

  • @WiktorStribiżew 在引号中的逗号旁边有空格时失败 (regex101.com/r/cW5hM0/2)。
  • @WiktorStribiżew 认为引号之外的任何内容都是不同的匹配项,无论逗号如何:regex101.com/r/cW5hM0/4(请注意其中的 k 字符)。
  • ([^,]+".*"[^,])+|([^,]?'.*'[^,])+|([^,]+) / g ,这应该可以工作并捕获您想要的组

标签: javascript regex


【解决方案1】:

好的,所以您的匹配组可以包含:

  • 只是字母
  • 一对匹配的“
  • 一对匹配的 '

所以这应该有效:

/((?:[^,"']+|"[^"]*"|'[^']*')+)/g

RegEx101 Demo

作为一个不错的奖励,您可以在双引号内删除额外的单引号,反之亦然。但是,您可能需要一个状态机来在双引号字符串中添加转义的双引号(例如“aa\”aa")。

不幸的是,它也匹配初始空间 - 您必须修剪匹配项。

【讨论】:

    【解决方案2】:

    使用双重前瞻来确定匹配的逗号在引号之外:

    /(?=(([^"]*"){2})*[^"]*$)(?=(([^']*'){2})*[^']*$)\s*,\s*/g
    
    • (?=(([^"]*"){2})*[^"]*$) 断言在匹配的逗号之前有偶数个双引号。
    • (?=(([^']*"){2})*[^']*$) 对单引号执行相同的断言。

    PS:这不处理不平衡、嵌套或转义引号的情况。

    RegEx Demo

    【讨论】:

      【解决方案3】:

      在 JavaScript 中试试这个

      (?:(?:[^,"'\n]*(?:(?:"[^"\n]*")|(?:'[^'\n]*'))[^,"'\n]*)+)|[^,\n]+
      

      Demo

      添加组以提高可读性(删除 ?name> for Javascript)

      (?<has_quotes>(?:[^,"'\n]*(?:(?<double_quotes>"[^"\n]*")|(?<single_quotes>'[^'\n]*'))[^,"'\n]*)+)|(?<simple>[^,\n]+)
      

      Demo

      解释:

      (?&lt;double_quotes&gt;"[^"\n]*") 匹配 "Any inside 但不是 "" = (1)(双引号)
      (?&lt;single_quotes&gt;'[^'\n]*') 匹配 'Any inside 但不是 '@ 987654330@ = (2)(单引号)
      (?:(?&lt;double_quotes&gt;"[^"\n]*")|(?&lt;single_quotes&gt;'[^'\n]*')) 匹配 (1)or(2) = (3)
      [^,"'\n]* 匹配任何文本,但不是 "', = (w)
      (?:(?:(?&lt;double_quotes&gt;"[^"\n]*")|(?&lt;single_quotes&gt;'[^'\n]*'))[^,"'\n]*) 匹配 (3)(w)
      (?:(?:(?&lt;double_quotes&gt;"[^"\n]*")|(?&lt;single_quotes&gt;'[^'\n]*'))[^,"'\n]*)+ 匹配重复 (3)(w) = ( 3w+)
      (?&lt;has_quotes&gt;[^,"'\n]*(?:(?:(?&lt;double_quotes&gt;"[^"\n]*")|(?&lt;single_quotes&gt;'[^'\n]*'))[^,"'\n]*)+) 匹配 (w)(3w+) = (4)(带引号)
      [^,\n]+ 匹配其他情况 (5)(简单)
      所以在最后我们有 (4)|(5) (有引号或简单)

      输入

      abcd,efgh, ijkl
      abcd, efgh, ij"k,l", mnop, 'q,rs't
      'q, rs't
      "'q,rs't, ij"k, l""
      

      输出:

      MATCH 1
      simple  [0-4]   `abcd`
      MATCH 2
      simple  [5-9]   `efgh`
      MATCH 3
      simple  [10-15] ` ijkl`
      MATCH 4
      simple  [16-20] `abcd`
      MATCH 5
      simple  [21-26] ` efgh`
      MATCH 6
      has_quotes  [27-35] ` ij"k,l"`
      double_quotes   [30-35] `"k,l"`
      MATCH 7
      simple  [36-41] ` mnop`
      MATCH 8
      has_quotes  [42-50] ` 'q,rs't`
      single_quotes   [43-49] `'q,rs'`
      MATCH 9
      has_quotes  [51-59] `'q, rs't`
      single_quotes   [51-58] `'q, rs'`
      MATCH 10
      has_quotes  [60-74] `"'q,rs't, ij"k`
      double_quotes   [60-73] `"'q,rs't, ij"`
      MATCH 11
      has_quotes  [75-79] ` l""`
      double_quotes   [77-79] `""`
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-11
        • 2016-03-27
        相关资源
        最近更新 更多