regex javascript正则表达式选择带引号的字符串而不是转义引号

1rhkuytd  于 2023-05-01  发布在  Java
关注(0)|答案(5)|浏览(131)

原始字符串:

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

想要获得:

"some \"string\"right here"

我使用的是下面的正则表达式:

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

kyxcudwk1#

使用解析器正确解析字符串

使用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);

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

不可能用懒点匹配模式匹配所需的字符串,因为它会在第一个"之前停止。如果你知道你的字符串在一个带引号的子字符串前永远不会有转义引号,并且如果你确定在双引号前没有文字\(这些条件对于安全地使用正则表达式来说是非常严格的),你可以使用

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

参见regex demo

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

JS演示:

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
sr4lhrrt

sr4lhrrt2#

安全的正则表达式方法

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

/"(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)
nbewdwxp

nbewdwxp3#

通用溶液:

  • 报价类型:单引号、双引号、反引号
  • 检测每个引用部分和引用类型
  • 允许转义引号位于引号部分内
  • 结果分为两组:(报价类型),

(?[“'])(?<inQuotes>(?:\\\1|.)*?)\1 或者,不使用组命名: ([“'])((?:\\1|.)*?)\1

3zwtqj6y

3zwtqj6y4#

你可以使用这个正则表达式:

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

[^\\]捕获任何不同于\的字符。所以“”不会被捕捉为比赛的开始或结束。

bqjvbblv

bqjvbblv5#

为了在忽略任何简单转义引号(\")的情况下从引号到引号进行匹配:

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

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

**编辑:**Wiktor StribiŽew正确地指出,字符串中有正则表达式项的更多情况将在我的初始答案中失败。例如\\",在您的情况下应该与"匹配。要避免此特定问题,您可以使用

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

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

相关问题