正则表达式在引号之外选择逗号

时间:2009-03-10 22:09:41

标签: regex quotes

我不太确定这是否可行,所以我转向你。

我想找一个正则表达式,它会选出所有不在引号集之外的逗号。

例如:

'foo' => 'bar',
'foofoo' => 'bar,bar'

这会在'bar',

之后选出第1行的单个逗号

我并不关心单引号和双引号。

有没有人有任何想法?我觉得这应该可以用readaheads,但我的正则表达式太弱了。

6 个答案:

答案 0 :(得分:81)

这将匹配任何字符串,包括第一个未引用的“,”。那是你想要的吗?

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

如果你想要所有这些(并且作为一个说不可能的人的反例)你可以写:

/(,)(?=(?:[^"]|"[^"]*")*$)/

将匹配所有这些。因此

'test, a "comma,", bob, ",sam,",here'.gsub(/(,)(?=(?:[^"]|"[^"]*")*$)/,';')

用分号替换引号内的所有逗号,并生成:

'test; a "comma,"; bob; ",sam,";here'

如果您需要它跨换行符,只需添加m(多行)标记。

答案 1 :(得分:10)

以下正则表达式将匹配双引号之外的所有逗号,

,(?=(?:[^"]*"[^"]*")*[^"]*$)

DEMO

OR (仅限PCRE)

"[^"]*"(*SKIP)(*F)|,

"[^"]*"匹配所有双引号块。也就是说,在此buz,"bar,foo"输入中,此正则表达式仅匹配"bar,foo"。现在,以下(*SKIP)(*F)使匹配失败。然后它移动到|符号旁边的模式,并尝试匹配剩余字符串中的字符。也就是说,在模式,旁边的输出|中,只会匹配buz之后的逗号。请注意,这不会匹配双引号内的逗号,因为我们已经使双引号部分跳过。

DEMO


以下正则表达式将匹配双引号内的所有逗号,

,(?!(?:[^"]*"[^"]*")*[^"]*$)

DEMO

答案 2 :(得分:2)

虽然可以用正则表达式来破解它(我喜欢和下一个人一样滥用正则表达式),但是迟早会在没有更高级的解析器的情况下尝试处理子字符串。遇到麻烦的可能方法包括混合引号和转义引号。

此函数将在逗号上拆分字符串,但不会在单引号或双引号字符串中分割逗号。可以使用其他字符轻松扩展它以用作引号(尽管字符对如«»需要更多代码行),甚至会告诉您是否忘记关闭数据中的引号:

function splitNotStrings(str){
  var parse=[], inString=false, escape=0, end=0

  for(var i=0, c; c=str[i]; i++){ // looping over the characters in str
    if(c==='\\'){ escape^=1; continue} // 1 when odd number of consecutive \
    if(c===','){
      if(!inString){
        parse.push(str.slice(end, i))
        end=i+1
      }
    }
    else if(splitNotStrings.quotes.indexOf(c)>-1 && !escape){
      if(c===inString) inString=false
      else if(!inString) inString=c
    }
    escape=0
  }
  // now we finished parsing, strings should be closed
  if(inString) throw SyntaxError('expected matching '+inString)
  if(end<i) parse.push(str.slice(end, i))
  return parse
}

splitNotStrings.quotes="'\"" // add other (symmetrical) quotes here

答案 3 :(得分:1)

试试这个正则表达式:

(?:"(?:[^\\"]+|\\(?:\\\\)*[\\"])*"|'(?:[^\\']+|\\(?:\\\\)*[\\'])*')\s*=>\s*(?:"(?:[^\\"]+|\\(?:\\\\)*[\\"])*"|'(?:[^\\']+|\\(?:\\\\)*[\\'])*')\s*,

这也允许使用“'foo\'bar' => 'bar\\',”等字符串。

答案 4 :(得分:1)

MarkusQ的回答对我来说很有用了大约一年,直到它没有。我刚刚在一行上有一个堆栈溢出错误,大约有120个逗号和3682个字符。在Java中,像这样:

        String[] cells = line.split("[\t,](?=(?:[^\"]|\"[^\"]*\")*$)", -1);

这是我非常不优雅的替代品,没有堆叠溢出:

private String[] extractCellsFromLine(String line) {
    List<String> cellList = new ArrayList<String>();
    while (true) {
        String[] firstCellAndRest;
        if (line.startsWith("\"")) {
            firstCellAndRest = line.split("([\t,])(?=(?:[^\"]|\"[^\"]*\")*$)", 2);
        }
        else {
            firstCellAndRest = line.split("[\t,]", 2);                
        }
        cellList.add(firstCellAndRest[0]);
        if (firstCellAndRest.length == 1) {
            break;
        }
        line = firstCellAndRest[1];
    }
    return cellList.toArray(new String[cellList.size()]);
}

答案 5 :(得分:1)

@SocialCensus,你在MarkusQ的评论中提供的例子,你在'旁边',并没有使用MarkusQ在上面给出的示例,如果我们将 sam 更改为< em> sam's :(测试,“逗号”,bob,“,sam's”,这里)与(,)无匹配(?=(?:[^“'] | [”|' ] [^“'] ”) $)。事实上,问题本身,“我真的不关心单引号和双引号”,是不明确的。你必须清楚你的意思通过引用“或”来引用。例如,是否允许嵌套?如果是这样,到多少级别?如果只有1个嵌套级别,内部嵌套引用之外的逗号会发生什么,但在外部嵌套引用内?你还应该考虑单引号自己作为撇号发生(即,就像我先前用sam所给出的反例)。最后,你制作的正则表达式并没有真正处理与双引号相同的单引号,因为它假设最后一种引号必须是双引号 - 用['|“替换最后一个双引号也有问题如果文本没有正确引用(或者如果使用了撇号),我想我们可能会假设所有引号都被正确描述。

MarkusQ的正则表达式回答了这个问题:找到所有逗号后面都有双引号的逗号(即,在双引号之外),并忽略所有逗号后面都有双引号的逗号(即,在双引号内)引号)。这通常与您可能想要的解决方案相同,但让我们看一些异常情况。首先,如果有人在结尾处留下引号,那么此正则表达式会找到所有错误的逗号,而不是找到所需的逗号或未匹配任何符号。当然,如果缺少双引号,则所有投注均已关闭,因为可能不清楚丢失的一个是否属于最终或者属于开头;然而,有一个案例是合法的,正则表达式可能会失败(这是第二个“异常”)。如果您调整正则表达式以跨越文本行,那么您应该知道引用多个连续段落要求您在每个段落的开头放置一个双引号,并在每个段落的末尾省略引用,除非在最后一段的结尾。这意味着在这些段落的空间中,正则表达式在某些地方会失败并在其他地方成功。

段落引用和嵌套引用的示例和简短讨论可以在http://en.wikipedia.org/wiki/Quotation_mark找到。