我目前有这个正则表达式来按所有空格分割字符串,除非它在引用的段中:
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"]
实现这一目标的最简单方法是什么?
答案 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]*)*
(?=\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);
哪个好。