javascript正则表达式选择引用的字符串但不是转义引号

时间:2016-07-25 08:55:25

标签: javascript regex

原始字符串:

some text "some \"string\"right here "

想要获得:

"some \"string\"right here"

我正在使用以下正则表达式:

/\"(.*?)\"/g

4 个答案:

答案 0 :(得分:2)

使用解析器

正确解析字符串

使用JavaScript正则表达式,无法以正确的双引号开始匹配。您将匹配转义的一个,或者在引用之前的文字\之后您将无法匹配正确的双引号。因此,最安全的方法是使用解析器。这是一个样本:



var s = "some text \\\"extras\" some \\\"string \\\" right\" here \"";
console.log("Incorrect (with regex): ", s.match(/"([^"\\]*(?:\\.[^"\\]*)*)"/g));
var res = [];
var tmp = "";
var in_quotes = false;
var in_entity = false;
for (var i=0; i<s.length; i++) {
  if (s[i] === '\\' && in_entity  === false) { 
     in_entity = true;
     if (in_quotes === true) {
       tmp += s[i];
     }
  } else if (in_entity === true) { // add a match
      in_entity = false;
      if (in_quotes === true) {
         tmp += s[i];
      }
  } else if (s[i] === '"' && in_quotes === false) { // start a new match
      in_quotes = true;
      tmp += s[i];
  } else if (s[i] === '"'  && in_quotes === true) { // append char to match and add to results
      tmp += s[i];
      res.push(tmp);
      tmp = "";
      in_quotes = false;
  } else if (in_quotes === true) { // append a char to the match
     tmp += s[i];
  } 
}
console.log("Correct results: ", res);
&#13;
&#13;
&#13;

不太安全的正则表达式方法

由于它将在第一个"之前停止,因此无法将所需的字符串与延迟点匹配模式匹配。 如果您知道您的字符串在引用的子字符串之前永远不会有转义引号,并且如果您确定双引号之前没有文字\ (并且这些条件非常严格,请使用安全的正则表达式,你可以使用

/"([^"\\]*(?:\\.[^"\\]*)*)"/g

请参阅regex demo

  • " - 匹配报价
  • ([^"\\]*(?:\\.[^"\\]*)*) - 0或更多序列
    • [^"\\]* - 0+非 - \和非"
    • (?:\\.[^"\\]*)* - 零个或多个序列
      • \\. - 任何转义符号
      • [^"\\]* - 0+非 - \和非"
  • " - 尾随报价

JS演示:

&#13;
&#13;
var re = /"([^"\\]*(?:\\.[^"\\]*)*)"/g; 
var str = `some text "some \\"string\\"right here " some text "another \\"string\\"right here "`;
var res = [];
while ((m = re.exec(str)) !== null) {
   res.push(m[1]);
}
document.body.innerHTML = "<pre>" + JSON.stringify(res, 0, 4) + "</pre>"; // Just for demo
console.log(res); // or another result demo
&#13;
&#13;
&#13;

答案 1 :(得分:0)

您可以使用此正则表达式:

/[^\\](\".*?[^\\]\")/g

[^\\]抓住任何与...不同的特征。因此,“不会成为比赛的开始或结束。

答案 2 :(得分:0)

为了在引用与引用匹配的同时忽略任何简单的转义引号(\"):

(:?[^\\]|^)(\"(:?.*?[^\\]){0,1}\")

意味着(:?开始分组,没有提取[^\\]匹配一个不是反斜杠|的字符匹配前一个字符串或^字符串的开头。 (提取分组的开始\"找到引号(跟随非斜杠或字符串的开头),(:?.*?[^\\]匹配以无斜线结尾的最短子字符串,){0,1}零次或一次 - 这实际上意味着一次或一个空的子字符串,后跟\"一个引号。

修改 WiktorStribiżew正确地指出,在我的初始答案中,字符串中使用正则表达式术语的更多案例将会失败。例如\\",在您的情况下应与"类似。要避免此特定问题,您可以使用

(:?[^\\]|^)((:?\\\\)*\"(:?.*?[^\\]){0,1}(:?\\\\)*\")

但是对于实际的正则表达式兼容性,您需要参考Wiktor的答案。

答案 3 :(得分:0)

安全正则表达式方法

补充@WiktorStribiżew's answer,有一种技术可以使用正则表达式在正确的双引号处开始匹配。它包括以下形式匹配引用和未引用的文本:

/"(quoted)"|unquoted/g

正如您所看到的,引用的文字由一个组匹配,因此我们只考虑match[1]反向引用的文字。

正则表达式

/"([^"\\]*(?:\\.[^"\\]*)*)"|[^"\\]*(?:\\.[^"\\]*)*/g

代码

var regex = /"([^"\\]*(?:\\.[^"\\]*)*)"|[^"\\]*(?:\\.[^"\\]*)*/g;
var s = "some text \\\"extras\" some \\\"string \\\" right\" here \"";
var match;
var res = [];

while ((match = regex.exec(s)) !== null) {
    if (match.index === regex.lastIndex)
        regex.lastIndex++;

    if( match[1] != null )
        res.push(match[1]); //Append to result only group 1
}

console.log("Correct results (regex technique): ",res)