一个更简单的正则表达式来解析带引号的字符串

7
问题很简单。我有一个包含多个元素的字符串,这些元素都嵌在单引号中:
var str = "'alice'   'anna marie' 'benjamin' 'christin'     'david' 'muhammad ali'"

我希望解析它,以便将所有这些名称存储在数组中:

result = [
 'alice',
 'anna marie',
 'benjamin',
 'christin',
 'david',
 'muhammad ali'
]

目前我正在使用以下代码执行此任务:

var result = str.match(/\s*'(.*?)'\s*'(.*?)'\s*'(.*?)'\s*'(.*?)'/);

但是这个正则表达式太长了,而且不够灵活,所以如果我在字符串 str 中有更多的元素,我就必须编辑这个正则表达式。
什么是最快和最有效的方法来进行解析?性能和灵活性对于我们的 Web 应用程序非常重要。
我已经查看了以下问题,但它们不是我的答案:
5个回答

10

只需定义一次模式,并使用全局标志g

var matches = str.match(/'[^']*'/g);

如果你想在没有单引号的情况下获取令牌,正常的方法是使用 REGEX 中的子匹配 - 但是当使用 g 标志时,JavaScript 不支持捕获子组。最简单(但不一定最有效)的方法是在迭代后去除它们:

if (matches)
    for (var i=0, len=matches.length; i<len; i++)
        matches[i] = matches[i].replace(/'/g, '');

[编辑] - 正如其他答案所说,你可以使用 split() 来代替,但是只有在你能够确信在你的字符串中每个标记之间始终存在一个空格(或某个常见分隔符)时才行。


2

一种不同的方法

我需要一种能够解析带引号和不带引号的字符串的方法,保留引号和非引号的顺序,并将它们用于React或React Native的特定标签输出。因此,我最终没有使用这里的答案,因为我不确定如何使它们适合我的需求,然后采取了以下方法。

function parseQuotes(str) {
  var openQuote = false;
  var parsed = [];
  var quote = '';
  var text = '';
  var openQuote = false;

  for (var i = 0; i < str.length; i++) {
    var item = str[i];
    if (item === '"' && !openQuote) {
      openQuote = true;
      parsed.push({ type: 'text', value: text });
      text = '';
    }
    else if (item === '"' && openQuote) {
      openQuote = false;
      parsed.push({ type: 'quote', value: quote });
      quote = '';
    }
    else if (openQuote) quote += item;
    else text += item;  
  }

  if (openQuote) parsed.push({ type: 'text', value: '"' + quote });
  else parsed.push({ type: 'text', value: text });

  return parsed;
}

当给出以下内容时:
'Testing this "shhhh" if it "works!" " hahahah!'

产生了以下结果:
[
  {
    "type": "text",
    "value": "Testing this "
  },
  {
    "type": "quote",
    "value": "shhhh"
  },
  {
    "type": "text",
    "value": " if it "
  },
  {
    "type": "quote",
    "value": "works!"
  },
  {
    "type": "text",
    "value": " "
  },
  {
    "type": "text",
    "value": "\" hahahah!"
  }
]

此功能可根据其内容轻松地将标签包装在其周围。

https://jsfiddle.net/o6seau4e/4/


1
当正则表达式对象设置了global标志时,您可以多次执行它来查找字符串中的所有匹配项。它通过在上次运行中匹配的最后一个字符之后开始下一次搜索来工作:
var buf = "'abc' 'def' 'ghi'";
var exp = /'(.*?)'/g;
for(var match=exp.exec(buf); match!=null; match=exp.exec(buf)) {
  alert(match[0]);
}

就我个人而言,我认为这是一种非常好的解析字符串的方法。

编辑:表达式/'(.*?)'/g匹配单引号(')之间的任何内容,修饰符*?是非贪婪的,它极大地简化了模式。


0

一种方式;

var str = "'alice' 'benjamin' 'christin' 'david'";
var result = {};

str.replace(/'([^']*)'/g, function(m, p1) {
    result[p1] = "";
});

for (var k in result) {
    alert(k);
}

0
如果有人需要更复杂的字符串解析,包括单引号或双引号以及转义引号的能力,这是正则表达式。在JS和Ruby中进行了测试。
r = /(['"])((?:\\\1|(?!\1).)*)(\1)/g
str = "'alice'  ddd vvv-12 'an\"na m\\'arie' \"hello ' world\" \"hello \\\" world\" 'david' 'muhammad ali'"
console.log(str.match(r).join("\n"))
  'alice'
  'an"na m\'arie'
  "hello ' world"
  "hello \" world"
  'david'
  'muhammad ali'

注意到未被引用的字符串没有被找到。如果目标是同时查找非引用单词,那么只需要进行一些小修复即可:

r = /(['"])((?:\\\1|(?!\1).)*)(\1)|([^'" ]+)/g
console.log(str.match(r).join("\n"))
  'alice'
  ddd
  vvv-12
  'an"na m\'arie'
  "hello ' world"
  "hello \" world"
  'david'
  'muhammad ali'

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接