【问题标题】:How to split a string by ',' or '[|]' unless the ',' is in '{}'除非 ',' 在 '{}' 中,否则如何用 ',' 或 '[|]' 分割字符串
【发布时间】:2023-03-11 05:58:01
【问题描述】:

我搜索一个正则表达式来拆分以下字符串:

aaa[bbb,ccc[ddd,{eee:1,mmm:999}],nnn[0,3]]
aaa[bbb,ccc[ddd,{eee:1, mmm:[123,555]}],nnn[0,3]]
aaa[bbb, ccc[ddd, ddd],nnn[0,3]]
aaa[bbb,ddd[0,3]]

由 '[' 或 ']' 或 ',' 除非 ',' 在 '{}' 中。例如:将 'aaa[bbb,ccc[ddd,' 拆分为 aaa, bbb, ccc, ddd 允许但不允许 {eee:1,mmm:999}。

结果:

aaa, bbb, ccc, ddd, {eee:1,mmm:999}, nnn, 0, 3
aaa, bbb, ccc, ddd, {eee:1, mmm:[123,555]}], nnn, 0, 3
aaa, bbb, ccc, ddd, ddd, nnn, 0, 3
aaa, bbb, ddd, 0, 3

我已经阅读了其他一些问题,但我无法修改正则表达式,因为有帖子可以做到这一点。

表达式的目标语言是 javascript。

【问题讨论】:

  • 正则表达式不“做”语言解析 :-(
  • {} 里面可以有 {} 吗?
  • 我不清楚你的“结果”是什么。你给我们看一个字符串吗?以子数组为条目的数组?

标签: javascript regex


【解决方案1】:

使用正则表达式和处理无限的嵌套大括号是不可能的;你需要一个基于堆栈的解析器。

【讨论】:

  • 因为当正则表达式引用 PCRE/等时它不是真的。看我的回答。
  • 它支持/[^][,{}]+|\{[^}]*}/ tho,这里没什么好看的。
  • @Qtax:那能处理嵌套大括号吗?
  • 你可以嵌套任何你想要的东西,除了 {},这似乎是这样。
【解决方案2】:

Perl/PCRE 正则表达式,也应该在 JS 中工作(只要 {} 没有嵌套):

$_ = 'aaa[bbb,ccc[ddd,{eee:1,mmm:999}],nnn[0,3]]
aaa[bbb,ccc[ddd,{eee:1, mmm:[123,555]}],nnn[0,3]]
aaa[bbb, ccc[ddd, ddd],nnn[0,3]]
aaa[bbb,ddd[0,3]]';

@r = /[^][,{}]+|\{[^}]*}/g;
print join ", ", @r;

输出:

aaa, bbb, ccc, ddd, {eee:1,mmm:999}, nnn, 0, 3,
aaa, bbb, ccc, ddd, {eee:1, mmm:[123,555]}, nnn, 0, 3,
aaa, bbb,  ccc, ddd,  ddd, nnn, 0, 3,
aaa, bbb, ddd, 0, 3

JavaScript 的粗略翻译:

var input =
    "aaa[bbb,ccc[ddd,{eee:1,mmm:999}],nnn[0,3]]\n" +
    "aaa[bbb,ccc[ddd,{eee:1, mmm:[123,555]}],nnn[0,3]]\n" +
    "aaa[bbb, ccc[ddd, ddd],nnn[0,3]]\n" +
    "aaa[bbb,ddd[0,3]]";

var re = /[^][,{}]+|\{[^}]*}/g;

var result = [];
while (!!(match = re.exec(input)))
{
    result.push(match[0]);
}

// Using <<value>> rather than just a comma, for clarity around
// whether and how "{...}" was processed or not.
write("<<" + result.join(">><<") + ">>");

尚不清楚问题中输入或结果数据中的换行符是什么意思。在上面,它们是输入数据中的换行符,然后在结果中没有特殊处理。如果需要特殊处理,OP可以适当编辑。这就是上面的结果(再次,使用&lt;&lt;&gt;&gt; 作为分隔符,而不是,,以明确{...} 是否被处理):

<<aaa>><<bbb>><<ccc>><<ddd>><<{eee:1,mmm:999}>><<nnn>><<0>><<3>><<
aaa>><<bbb>><<ccc>><<ddd>><<{eee:1, mmm:[123,555]}>><<nnn>><<0>><<3>><<
aaa>><<bbb>><< ccc>><<ddd>><< ddd>><<nnn>><<0>><<3>><<
aaa>><<bbb>><<ddd>><<0>><<3>>

【讨论】:

  • @SLaks:它似乎非常接近,至少在所提供的测试数据(和问题陈述)和我(也许是天真的)翻译的范围内(稍后我将对其进行编辑)。
  • 为免生疑问:我并不是说我会这样做(我认为我根本不会为此使用正则表达式,除了扫描中断),只是提供了一个粗略的翻译,因为 Qtax 刚刚提供了 Perl/PCRE。
【解决方案3】:

一种非正则表达式的方法是编写一个逐字符检查字符串的循环。当它遇到{ 时,增加一个变量。当它遇到} 时,减少一个变量。当它遇到 , 并且您递增/递减的变量为零时,将 , 的位置添加到列表中。完成后,您将获得要拆分字符串的位置列表。

我假设在打开大括号 { 之前没有任何右大括号 },否则您可能希望忽略放错位置的右大括号,而不是将变量减为负数。

【讨论】:

  • +1 我可能不会逐个字符地进行(我会使用[{,[\]}] 的正则表达式来扫描中断),但是是的,我想我可能会这样做像这样的东西,而不是试图在可能最适合其他逻辑的问题上强制使用纯正则表达式解决方案。
【解决方案4】:

将 {stuff} 分开,其余部分分开-

function customRx(s){
 s= s.replace(/[\[\],\s]+$/g,'');
 var Rx=/,?(\{[^}]+\}),?/g, Rs=/[\[\],\s]+/, Rc=/^,|,$/g;
 var A= [], i= 0, M, z= 0;
 while((M= Rx.exec(s))!= null){
  i= M.index;
  if(i> z){
   A.push(s.substring(z, i).split(Rs));
  }
  z= Rx.lastIndex;
  A.push(s.substring(i, z).replace(Rc,''));
 }
 if(s.length> z){
  A.push(s.substring(z).split(Rs));
 }
 return A;
}

// 测试

var s1= 'aaa[bbb,ccc[ddd,{eee:1,mmm:999}],nnn[0,3]]'+
'aaa[bbb,ccc[ddd,{eee:1, mmm:[123,555]}],nnn[0,3]]'+
'aaa[bbb, ccc[ddd, ddd],nnn[0,3]]'+
'aaa[bbb,ddd[0,3]]';

alert(customRx(s1).join(', '));

返回值(添加了换行符)>

aaa,bbb,ccc,ddd, {eee:1,mmm:999},

nnn,0,3,aaa,bbb,ccc,ddd, {eee:1, mmm:[123,555]},

nnn,0,3,aaa,bbb,ccc,ddd,ddd,nnn,

0,3,aaa,bbb,ddd,0,3

【讨论】:

    【解决方案5】:

    假设您正在逐行处理文本,并且大括号不能嵌套,这个拆分正则表达式应该可以工作:

    / *[\[\],]+ *(?=[^{}]*(?:\{[^{}]*\}[^{}]*)*$)/
    

    第一部分 -- *[\[\],]+ * -- 匹配 [], 中的一个或多个以及任何周围的空格。其余的是前瞻,它断言,如果匹配字符前面有任何大括号,它们就会成对出现。如果文本格式正确,则可以确保匹配不会出现在一对大括号内。

    【讨论】:

    • / *[][,]+ *(?![^{]*})/,如果字符串没有格式错误
    猜你喜欢
    • 1970-01-01
    • 2011-01-28
    • 1970-01-01
    • 1970-01-01
    • 2020-04-26
    • 2016-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多