2013-03-19 65 views
1

我想分割逗号分隔对字符串,但无法解决如何迎合包含逗号。Java正则表达式 - 迎合包含逗号

这里是我的测试案例 -

private void stringSplit() { 
    String value = "{aaa=1111,bbb=2222,ccc=3333}"; 
    String regEx = "[^,]+=[^,]+"; 
    String separator = "="; 
    final Pattern pattern = Pattern.compile(regEx); 
    final Matcher matcher = pattern.matcher(value); 
    while (matcher.find()) { 
     final String group = matcher.group(); 
     final String key = group.substring(0, group.indexOf(separator)); 
     final String val = 
     group.substring(
      group.indexOf(separator) + separator.length(), 
      group.length()); 
     System.out.println("key [" + key + "], val [" + val + "]"); 
    } 
} 

,这里是我的结果 -

key [{aaa], val [1111] 
key [bbb], val [2222] 
key [ccc], val [3333}] 

所有好为止......

但有可能在数字逗号值即

"{aaa=11,11,bbb=2222,ccc=333,3}"; 

我想要的结果是 -

key [{aaa], val [11,11] 
key [bbb], val [2222] 
key [ccc], val [333,3}] 

难道你们任何一个正则表达式大师的帮助我在这里。

谢谢!

编辑

从@继bmorris591进一步的评论。

好吧,我有一个最终查询 - 这是一个这个疯狂的正则表达式(+一些java代码)需要处理的权威列表。

这里是我的代码 -

private void stringSplit() { 
    String value = "{1=\"1, one\", 22=\"+t,w,o\", 333=\"three, \"3\", -33,,333,\", 4444=\"four. '4-4, (44), -44\"}, 555=\"\", \"666\"=6666, \"777\"=\"7777\"}"; 
    String regex = "[^\\{,]+=([[\\w]\\(\\)\\-\\+\\.\"'\\s,]+)[,}]"; 
    String separator = "="; 
    final Pattern pattern = Pattern.compile(regex); 
    final Matcher matcher = pattern.matcher(value); 
    while (matcher.find()) { 
     final String group = matcher.group(); 
     showKeyAndValue(group, separator); 
    } 
} 

private void showKeyAndValue(final String group, final String keyValueSeparator) { 
    System.out.println("group [" + group + "]"); 
    final String key = removeQuotesFromString(group.substring(0, 
      group.indexOf(keyValueSeparator))); 
    final String val = removeQuotesFromString(group.substring(
      group.indexOf(keyValueSeparator) 
        + keyValueSeparator.length(), group.length())); 
    System.out.println("key [" + key + "], val [" + val + "]"); 
} 

private String removeQuotesFromString(final String str) { 
    String returnString = str.trim(); 
    if (returnString.startsWith("\"")) { 
     returnString = returnString.substring(
       returnString.indexOf("\"") + 1, returnString 
         .lastIndexOf("\"")); 
    } 
    return returnString; 
} 

而且这里的结果 -

group [1="1, one",] 
key [1], val [1, one] 
group [ 22="+t,w,o",] 
key [22], val [+t,w,o] 
group [ 333="three, "3", -33,,333,",] 
key [333], val [three, "3", -33,,333,] 
group [ 4444="four. '4-4, (44), -44"}] 
key [4444], val [four. '4-4, (44), -44] 
group [ 555="",] 
key [555], val [] 
group [ "666"=6666,] 
key [666], val [6666,] 
group [ "777"="7777"}] 
key [777], val [7777] 

所有的结果是正确的除了从钥匙666正如你可以看到有一个结尾逗号。现在,我可以剥夺这一关(对于引号封装(基本上是一个数)),但我想知道,这可能会在正则表达式来来达到的,因为这将是一个“清洁”的解决方案..

很多很多非常感谢,如果你能想到任何东西。

+0

首先来看看,我说你内在的逗号最明显的标准就是后面会有一个逗号或者什么也没有。但是如果你匹配一个逗号,接下来的事情之一就是一个=,那么它就是你的一个分裂的。 – Loki 2013-03-19 17:00:58

回答

2

可以使用负前瞻的魔力,对一个逗号分割的字符串后面没有一个数字使用

public static void main(String[] args) { 
    final String s = "{aaa=11,11,bbb=2222,ccc=333,3}"; 
    final String[] ss = s.substring(1, s.length() -1).split(",(?!\\d)"); 
    for(final String str : ss) { 
     System.out.println(str); 
    } 
} 

输出

aaa=11,11 
bbb=2222 
ccc=333,3 

您可以轻松地扩展这个猛拉直接键=值对

public static void main(String[] args) { 
    final String s = "{aaa=11,11,bbb=2222,ccc=333,3}"; 
    final Pattern p = Pattern.compile("([A-Za-z]++)=([\\d,]+)(?!\\d)[,}]"); 
    final Matcher matcher = p.matcher(s); 
    while (matcher.find()) { 
     System.out.println(matcher.group(1)); 
     System.out.println(matcher.group(2)); 
     System.out.println("DONE"); 
    } 
} 

输出

aaa 
11,11 
DONE 
bbb 
2222 
DONE 
ccc 
333,3 
DONE 

编辑

继OP的评论:

该货币对字母数字(包括,+-*/=())的值部分,也值总是在引号封装,有可能也是,+-*/=()的多重发生...

我修改了表达式:

public static void main(String[] args) { 
    final String s = "{1=\"1, one\", 22=\"+t,w,o\", 333=\"three, 3, -33,,333\", 4444=\"four. 4-4, (44), -44\"}"; 
    System.out.println("String is: " + s); 
    final Pattern p = Pattern.compile("([^{=,\\s]++)=\"([^\"]++)\""); 
    final Matcher matcher = p.matcher(s); 
    while (matcher.find()) { 
     System.out.println(matcher.group(1)); 
     System.out.println(matcher.group(2)); 
     System.out.println("DONE"); 
    } 

输出:

String is: {1="1, one", 22="+t,w,o", 333="three, 3, -33,,333", 4444="four. 4-4, (44), -44"} 
1 
1, one 
DONE 
22 
+t,w,o 
DONE 
333 
three, 3, -33,,333 
DONE 
4444 
four. 4-4, (44), -44 
DONE 

的图案将现在匹配任何不是=,{或空白后跟=再接着由不含"包封在"任何图案。 这有帮助吗?

+0

是的!!!我已将您的答案加入书签!简洁明了,像Cristal。 – Aubin 2013-03-19 17:03:45

+0

@Aubin很高兴你喜欢它 - 从来没有听到任何人称之为“清晰如水晶”的正则表达式... – 2013-03-19 17:09:24

+0

感谢您的回复。不幸的是,我原来的帖子太简单了。我已经重新发布了更新... – Hallam 2013-03-21 10:52:26

0

bmorris591

感谢您的回复。

对不起,但回头看我原来的帖子太简单了。

一对中的部分是字母数字(包括”,+ - */=() “),也值为总是封装在引号,有可能是” 多occurances,+ - */=()”太...

"{1=\"1 one\", 22=\"two\", 333=\"three 3\"}" 
"{1=\"1, one\", 22=\"+t,w,o\", 333=\"three, 3, -33,,333\", 4444=\"four. 4-4, (44), -44\"}" 

由于这种复杂性,我认为最简单的办法是对字符串之前与一些标记字符替换逗号的所有出现被构造,做正则表达式和th恩逗号重新应用到价值...

谢谢您的回复我的初始后,虽然因为它我原来的问题的解决方案......