使用正则表达式按逗号分割,但不要在括号内进行分割。

7
我想通过逗号来分割字符串,但是不希望在括号内进行分割。
例如:
"[1, '15', [false]], [[], 'sup']"

会分成
[
  "[1, '15', [false]]",
  "[[], 'sup']"
]

我曾尝试使用/\,(?=(.*\[.*\])*.*\]{1})/作为我的正则表达式,我的逻辑是匹配逗号,如果其后跟着一个奇数个'[]'且中间和外部有任意字符,然后紧跟着一个']'。


第一个示例中的数组字面量是否有效? - guest271314
@guest271314:OP说他们有一个字符串,因此可以假设这是一个字符串的内容。 - Felix Kling
@FelixKling:“但是当它们在数组元素内部时就不行了。” 给定初始字符串,如何确定哪个是数组元素?在 ]],[[ 处拆分即可。 - guest271314
抱歉,整个东西是一个字符串。 - JiniHendrix
生成的字符串是否可解析为 JavaScript 对象或有效的 JSON?还是只返回 OP 描述的结果? - guest271314
只返回 op 描述的结果。 - JiniHendrix
3个回答

6

正则表达式不适合涉及嵌套的情况。您可能需要编写一个小型解析器:

function parse(str) {
  let result = [], item = '', depth = 0;

  function push() { if (item) result.push(item); item = ''; }

  for (let i = 0, c; c = str[i], i < str.length; i++) {
    if (!depth && c === ',') push();
    else {
      item += c;
      if (c === '[') depth++;
      if (c === ']') depth--;
    }
  }
  
  push();
  return result;
}
        
console.log(parse("[1, '15', [false]], [[], 'sup']"));

你可能需要调整这个功能来处理逗号周围的空格,不平衡的方括号等。


这真的很好,非常感谢。 - JiniHendrix

2
如果期望的结果是两个字符串,无论这些字符串是否可解析为javascript对象或有效的JSON,您可以使用Array.prototype.reduce()String.prototype.split()String.prototype.replace()。请注意保留HTML标签。

var str = "[1, '15', [false]], [[], 'sup']";

var res = str.split(/,/).reduce((arr, text) => {

  text = text.trim();

  if (arr.length === 0) {
    arr.push([]);
  }
 
  if (/^\[/.test(text) && !/\]$/.test(text)) {
     arr[arr.length === 1 ? 0 : arr.length - 1].push(text.slice(1));
     return arr
  }
 
  if (!/^\[/.test(text) && /\]$/.test(text)) {
     arr[arr.length === 1 ? 0 : arr.length - 1].push(text.slice(0, -1));
     return arr
  }

  if (!/^\[/.test(text) && !/\]$/.test(text) 
      || /^\[/.test(text) && /\]{2}$/.test(text) 
      || !/\[|\]/.test(text)) {
      arr[arr.length === 1 ? 0 : arr.length - 1].push(text);
     return arr
  }
  
  if (/^\[{2}/.test(text) && /\]$/.test(text)) {
     arr[arr.length - 1].push(text);
     return arr
  }

  return arr

}, []);

var strs = `[${res.join()}]`.replace(/"/g, "").split(/,(?=\[{2})|"(?=")/);

console.log(`str1:${strs[0]}\nstr2:${strs[1]}`);


0
如果字符串是类似数组的字符串...也许这也值得一试:
 var regex = /(\[.*?\]\])|(\[\[.*?\]$)|(\[(.*?)\])|(,)/gm;

var regex = /(\[.*?\]\])|(\[\[.*?\]$)|(\[(.*?)\])|(,)/gm;
str = "[1, '15', [false]], [[], 'sup']";
/*str="[1, [30] [false][,]], [[]false, 'sup'[]]";
str="[[] []], [1,4,5[8]]";
str="[[1,2,3],[3,6,7]],[[],566,[]]";
str="[[],[]],['duh,[],'buh',[]]";

str="[1,2,3],[5,'ggg','h']"*/


arr=[];
while ((matches = regex.exec(str)) !== null) {
if(matches[0]!==',')
arr.push(matches[0]);

  
}

console.log(arr);

所以,基本上,匹配备选组,循环遍历结果,保留非逗号匹配。这可能在某些情况下会失败...但是,应该进行更多测试。

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