分裂的正则表达式模式

时间:2013-08-01 05:32:46

标签: java regex parsing

我想解决这个问题。

  • ,逗号:拆分条款
  • "双引号:字符串值(忽略特殊字符)
  • []数组

例如:

输入:a=1,b="1,2,3",c=[d=1,e="1,2,3"]

预期产出:

    a=1
    b="1,2,3"
    c=[d=1,e="1,2,3"]

但我无法超越结果。

我写了下面的代码:

 String line = "a=1,b=\"1,2,3\",c=[d=1,e=\"1,11\"]";
 String[] tokens = line.split(",(?=(([^\"]*\"){2})*[^\"]*$)");
 for (String t : tokens)
      System.out.println("> " + t);

我的输出是:

a=1
b="1,2,3"
c=[d=1
e="1,11"]

我需要更改什么才能获得预期的输出?我应该坚持正则表达式还是其他解决方案更灵活,更容易维护?

2 个答案:

答案 0 :(得分:52)

这个正则表达式可以解决问题:

",(?=(([^\"]*\"){2})*[^\"]*$)(?=([^\\[]*?\\[[^\\]]*\\][^\\[\\]]*?)*$)"

它的工作原理是在逗号后添加一对方括号的匹配 - 如果你在里面一个方括号的术语,当然你不会有平衡括号跟随。

这是一些测试代码:

String line = "a=1,b=\"1,2,3\",c=[d=1,e=\"1,11\"]";
String[] tokens = line.split(",(?=(([^\"]*\"){2})*[^\"]*$)(?=([^\\[]*?\\[[^\\]]*\\][^\\[\\]]*?)*$)");
for (String t : tokens)
    System.out.println(t);

输出:

a=1
b="1,2,3"
c=[d=1,e="1,11"]

答案 1 :(得分:0)

我知道这个问题差不多有一年了,但是......这个正则表达式要简单得多:

\[[^]]*\]|"[^"]*"|(,)
  • |的最左侧分支与[complete brackets]
  • 匹配
  • |的下一侧与\"strings like this\"
  • 相匹配
  • 右侧将逗号捕获到第1组,我们知道它们是正确的逗号,因为它们与左侧的表达不匹配
  • 我们需要做的只是拆分第1组

拆分第1组捕获

您可以这样做(请参阅online demo底部的输出):

String subject = "a=1,b=\"1,2,3\",c=[d=1,e=\"1,11\"]";
Pattern regex = Pattern.compile("\\[[^]]*\\]|\".*?\"|(,)");
Matcher m = regex.matcher(subject);
StringBuffer b= new StringBuffer();
while (m.find()) {
if(m.group(1) != null) m.appendReplacement(b, "@@SplitHere@@");
else m.appendReplacement(b, m.group(0));
}
m.appendTail(b);
String replaced = b.toString();
String[] splits = replaced.split("@@SplitHere@@");
for (String split : splits) System.out.println(split);

这是一个两步分割:首先,我们用一些独特的东西替换逗号,例如@@SplitHere@@

优点和缺点

  • 这项技术的主要好处是它非常容易理解和维护。如果您突然决定排除逗号{inside , curlies},则只需在正则表达式左侧添加另一个OR分支:{[^{}]*}
  • 熟悉它时,可以在很多情况下使用它
  • 在这种情况下,主要的缺点是我们在拆分之前进行两个步骤。在我看来,与现代处理器无关。可维护的代码更为重要。

参考

这种技术有很多应用。这两个链接完全解释了这一点。