按空格拆分字符串,保留带引号的段,允许转义引号

时间:2010-10-27 09:54:38

标签: javascript regex

我目前有这个正则表达式来按所有空格分割字符串,除非它在引用的段中:

keywords = 'pop rock "hard rock"';
keywords = keywords.match(/\w+|"[^"]+"/g);
console.log(keywords); // [pop, rock, "hard rock"]

但是,我也希望可以在关键字中使用引号,例如:

keywords = 'pop rock "hard rock" "\"dream\" pop"';

这应该返回

[pop, rock, "hard rock", "\"dream\" pop"]

实现这一目标的最简单方法是什么?

4 个答案:

答案 0 :(得分:28)

您可以将正则表达式更改为:

keywords = keywords.match(/\w+|"(?:\\"|[^"])+"/g);

而不是[^"]+你有(?:\\"|[^"])+允许\"或其他字符,而不是未转义的引号。

一个重要的注意事项是,如果您希望字符串包含文字斜杠,则应为:

keywords = 'pop rock "hard rock" "\\"dream\\" pop"'; //note the escaped slashes.

此外,\w+[^"]+之间存在轻微的不一致 - 例如,它会匹配单词"ab*d",但不匹配ab*d(不带引号)。请考虑使用[^"\s]+代替非空格。

答案 1 :(得分:4)

ES6解决方案支持:

  • 除了内部引号外,按空格分割
  • 删除引号但不包含反斜杠转义引号
  • 逃脱报价成为报价
  • 可以在任何地方加上引号

代码:

keywords.match(/\\?.|^$/g).reduce((p, c) => {
        if(c === '"'){
            p.quote ^= 1;
        }else if(!p.quote && c === ' '){
            p.a.push('');
        }else{
            p.a[p.a.length-1] += c.replace(/\\(.)/,"$1");
        }
        return  p;
    }, {a: ['']}).a

输出:

[ 'pop', 'rock', 'hard rock', '"dream" pop' ]

答案 2 :(得分:1)

如果Kobi的答案适用于示例字符串,那么当Tim Pietzcker在评论中注意到它时,引号之间有多个连续的转义字符(反斜杠)。要处理这些情况,模式可以像一样编写(对于匹配方法)

(?=\S)[^"\s]*(?:"[^\\"]*(?:\\[\s\S][^\\"]*)*"[^"\s]*)*

demo

(?=\S)确保当前位置至少有一个非空格字符,因为以下内容描述了所有允许的子字符串(包括引号之间的空格)完全是可选的。

详细说明:

(?=\S)   # followed by a non-whitespace
[^"\s]*  #"# zero or more characters that aren't a quote or a whitespace
(?: # when a quoted substring occurs:
    "       #"# opening quote
    [^\\"]* #"# zero or more characters that aren't a quote or a backslash
    (?: # when a backslash is encountered:
        \\ [\s\S] # an escaped character (including a quote or a backslash)
        [^\\"]* #"#
    )*
    "         #"# closing quote
    [^"\s]*   #"#
)*

答案 3 :(得分:0)

我想指出我和你有相同的正则表达式,

/\w+|"[^"]+"/g

但它没有用于空引用的字符串,例如:

"" "hello" "" "hi"

所以我不得不用*来改变+量词。 这给了我:

str.match(/\w+|"[^"]*"/g);

哪个好。

(例如:https://regex101.com/r/wm5puK/1