用于分析带引号的字符串的更简单的正则表达式

A simpler regular expression to parse quoted strings

本文关键字:字符串 更简单 正则表达式 用于      更新时间:2023-09-26

问题很简单。我有一个字符串,其中包含嵌入在单引号中的多个元素:

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 应用程序中很重要。

我看过以下问题,但它们不是我的答案:

  • 带引号的字符串的正则表达式
  • 正则表达式 - 如何查找单词和引用短语

定义模式一次并使用全局g标志。

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

如果你想要的令牌周围没有单引号,正常的方法是在 REGEX 中使用子匹配 - 但是 JavaScript 不支持在使用 g 标志时捕获子组。解决此问题的最简单(尽管不一定是最有效的)方法是在之后迭代地删除它们:

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

[编辑] - 正如其他答案所说,您可以使用split()代替,但前提是您可以依赖字符串中的每个标记之间始终有一个空格(或一些公共分隔符)。

一种不同的方法

我来到这里需要一种方法,可以解析引号和非引号的字符串,保留引号和非引号的顺序,然后输出它,并带有特定的标签包裹在它们周围,用于 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/

当正则表达式对象设置了 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匹配单引号(')之间的任何内容,修饰符*?是非贪婪的,它大大简化了模式。

单向;

var str = "'alice' 'benjamin' 'christin' 'david'";
var result = {};
str.replace(/'([^']*)'/g, function(m, p1) {
    result[p1] = "";
});
for (var k in result) {
    alert(k);
}

如果有人来到这里并且需要更复杂的字符串解析,同时使用单引号或双引号以及转义引号的能力,这就是正则表达式。在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'