2012-01-27 891 views
21

我有一个字符串,它看起来像下面这样:正则表达式只匹配不在括号内的逗号?

12,44,foo,bar,(23,45,200),6 

我想创建一个逗号匹配的正则表达式,但只有那些没有括号内(在上面的例子中的逗号,所有除23和45之后的两个逗号之外)。我如何做到这一点(Java正则表达式,如果这有所作为)?

+2

还能有嵌套的括号?能有多一对吗? – Nikodemus 2012-01-27 07:10:17

+1

字符串可以有不匹配的括号,比如'“,12,44,12)foo,bar,(23,45,200),6”'? – anubhava 2012-01-27 07:30:37

回答

44

假设不可能有嵌套的括号(否则,您不能使用Java正则表达式完成这个任务,因为递归匹配不支持):

Pattern regex = Pattern.compile(
    ",   # Match a comma\n" + 
    "(?!  # only if it's not followed by...\n" + 
    " [^(]* # any number of characters except opening parens\n" + 
    " \\)  # followed by a closing parens\n" + 
    ")   # End of lookahead", 
    Pattern.COMMENTS); 

此正则表达式使用negative lookahead assertion,以确保括号后面的下一个(如果有的话)不是右括号。只有这样逗号才可以匹配。

+3

很好的解释。我新注册前。新西兰人开始了解你的答案。谢谢 – praveenb 2012-08-11 09:12:13

+4

使用'Pattern.COMMENTS'很好的演示。这是所有正则表达式在stackoverflow上的答案应该是这样的。 – Wilt 2016-05-03 09:12:43

+0

@Tim是否有任何正则表达式,我可以使用这个字符串“12,44,foo,bar,(23,45,200(10,11(23))),6”。上面的逻辑失败,我提到的字符串。 – fidato 2018-01-01 15:36:33

-4

我不明白对正则表达式的这种痴迷,因为它们不适用于大多数用于它们的任务。

String beforeParen = longString.substring(longString.indexOf('(')) + longString.substring(longString.indexOf(')') + 1); 
int firstComma = beforeParen.indexOf(','); 
while (firstComma != -1) { 
    /* do something. */ 
    firstComma = beforeParen.indexOf(',', firstComma + 1); 
} 

(当然这个假设存在总是只有一个开括号和一个匹配的右括号后它的到来somewhen。)

+2

它假定括号后没有逗号。你测试过了吗?它甚至在Paul提供的示例字符串上失败。编写一个正确的解析器,也不会扼杀格式错误的输入,可能和编写正确的正则表达式一样困难(如果不是更难)。如果输入符合定义的标准,我会*非常喜欢在这个用例中使用正则表达式。 – 2012-01-27 12:06:11

+0

你是对的,我在完成paranthesis后忽略了这部分。固定。 :) – Bombe 2012-01-27 12:13:55

+1

你如何处理像1,2,(3,4),5,6,(7,8)'这样的输入? – 2012-01-27 12:32:25

5

保罗,复活这个问题,因为它有一个简单的解决方案,这是不提及。 (在为regex bounty quest做一些研究时发现了你的问题。)

此外,现有解决方案检查逗号后面没有括号,但不能保证它嵌入括号中。

的正则表达式是非常简单的:

\(.*?\)|(,) 

交替的左侧完整的括号匹配。我们将忽略这些匹配。右侧与第1组匹配并捕获逗号,并且我们知道它们是正确的逗号,因为它们与左侧的表达式不匹配。

在此demo中,您可以在右下方的窗格中看到组1捕获。

你说你想匹配逗号,但你可以使用相同的一般想法来拆分或替换。

为了匹配逗号,你需要检查第1组。这个完整程序唯一的目标就是做到这一点。

import java.util.*; 
import java.io.*; 
import java.util.regex.*; 
import java.util.List; 

class Program { 
public static void main (String[] args) throws java.lang.Exception { 

String subject = "12,44,foo,bar,(23,45,200),6"; 
Pattern regex = Pattern.compile("\\(.*?\\)|(,)"); 
Matcher regexMatcher = regex.matcher(subject); 
List<String> group1Caps = new ArrayList<String>(); 

// put Group 1 captures in a list 
while (regexMatcher.find()) { 
if(regexMatcher.group(1) != null) { 
group1Caps.add(regexMatcher.group(1)); 
} 
} // end of building the list 

// What are all the matches? 
System.out.println("\n" + "*** Matches ***"); 
if(group1Caps.size()>0) { 
for (String match : group1Caps) System.out.println(match); 
} 
} // end main 
} // end Program 

这里是一个live demo

要使用相同的技术用于分离或更换,请参阅参考文章中的代码示例。

参考

  1. How to match pattern except in situations s1, s2, s3
  2. How to match a pattern unless...