2013-01-03 182 views
2

我想提取分隔符(在这种情况下是括号内)的字符串发生但不是在引号(单或双)内的字符串发生。以下是我已经尝试 - 这个表达式取括号内所有出现的,这也用引号(我不想引号内的)正则表达式来提取分隔符内的字符串

public class RegexMain { 
    static final String PATTERN = "\\(([^)]+)\\)"; 
    static final Pattern CONTENT = Pattern.compile(PATTERN); 
    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 
     String testString = "Rhyme (Jack) and (Jill) went up the hill on \"(Peter's)\" request."; 
     Matcher match = CONTENT.matcher(testString); 
     while(match.find()) { 
      System.out.println(match.group()); // prints Jack, Jill and Peter's 
     } 
    } 
} 
+0

如果我是你,我会首先用空字符串替换引用的部分,然后查找匹配的组。这不是一种选择吗? – inhan

回答

1

你可以尝试

public class RegexMain { 
    static final String PATTERN = "\\(([^)]+)\\)|\"[^\"]*\""; 
    static final Pattern CONTENT = Pattern.compile(PATTERN); 
    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 
     String testString = "Rhyme (Jack) and (Jill) went up the hill on \"(Peter's)\" request."; 
     Matcher match = CONTENT.matcher(testString); 
     while(match.find()) { 
      if(match.group(1) != null) { 
       System.out.println(match.group(1)); // prints Jack, Jill 
      } 
     } 
    } 
} 

此模式将匹配带引号的字符串以及括号的人,但只有那些括号内将装上去group(1)。由于+*在正则表达式中是贪婪的,所以它宁愿匹配"(Peter's)"而不是(Peter's)

+0

+1,我修改了正则表达式为“\\(([^)] +)\\)| \”[^ \“] * \”|'[^'] *'“,然后还包括而且,作为替代,我们仍然可以使用match.group(0)(只处理以括号开头的字符串)。但是,在接受这个答案之前我会等待,因为我相信应该有一种方法直接使用正则表达式(而不必处理组(0)和组(1) - 我只是不知道如何。 – Scorpion

0

注意的:这不是最终响应因为我不熟悉JAVA,但我相信它仍然可以转换成JAVA语言。

就我而言,最简单的方法是用空字符串替换字符串中的引用部分,然后查找匹配。希望你对PHP有点熟悉,这里有个想法。

$str = "Rhyme (Jack) and (Jill) went up the hill on \" (Peter's)\" request."; 

preg_match_all(
    $pat = '~(?<=\().*?(?=\))~', 
    // anything inside parentheses 
    preg_replace('~([\'"]).*?\1~','',$str), 
    // this replaces quoted strings with '' 
    $matches 
    // and assigns the result into this variable 
); 
print_r($matches[0]); 
// $matches[0] returns the matches in preg_match_all 

// [0] => Jack 
// [1] => Jill 
+0

可能有单引号和双引号,将声音转换为解决方法。理想情况下,我想要一个正则表达式来完成这项工作。 – Scorpion

+0

@Scorpion有许多可能会打破模式。因为lookbehead和lookahead不够灵活,无法处理像'*','?'和'+'这样的特殊字符,所以编写单个正则表达式来执行所需操作可能几乎是不可能的。但我会看这个问题,我很好奇别人会想出什么。 – inhan

1

这种情况下,您可以优雅地使用look-behind和look-ahead操作符来实现您想要的功能。这里有一个Python解决方案(我总是用它在命令行上快速尝试),但正则表达式在Java代码中应该是相同的。

此正则表达式匹配前面有左括号的内容,使用正面后视,并且使用正面预见后面的右括号成功。但是,当左括号前面有一个使用负面后视的单引号或双引号时,以及当使用负面先行视图的右单引号或双引号使右闭合圆括号成功时,它会避免这些匹配。

In [1]: import re 

In [2]: s = "Rhyme (Jack) and (Jill) went up the hill on \"(Peter's)\" request." 

In [3]: re.findall(r""" 
    ...:  (?<=    # start of positive look-behind 
    ...:   (?<!   # start of negative look-behind 
    ...:    [\"\']  # avoids matching opening parenthesis preceded by single or double quote 
    ...:  )    # end of negative look-behind 
    ...:   \(   # matches opening parenthesis 
    ...: )     # end of positive look-behind 
    ...:  \w+ (?: \'\w*)? # matches whatever your content looks like (configure this yourself)    
    ...:  (?=    # start of positive look-ahead 
    ...:   \)    # matches closing parenthesis 
    ...:   (?!   # start of negative look-ahead 
    ...:    [\"\']  # avoids matching closing parenthesis succeeded by single or double quote 
    ...:  )    # end of negative look-ahead 
    ...: )     # end of positive look-ahead 
    ...:  """, 
    ...:  s, 
    ...:  flags=re.X) 
Out[3]: ['Jack', 'Jill'] 
+0

不幸的是我不明白Python构造(re.findall)太好, t用java试试吧 – Scorpion

+0

@Scorpion正如你在我的例子中看到的,['re.findall()'](http://docs.python.org/2.7/library/re.html#re.findall)返回在一个字符串中一个模式的所有非重叠事件。您的Java代码基本上使用['Matcher.find()'](http://docs.oracle.com/javase/7/docs/api/java/ util/regex/Matcher.html#find%28%29)在'while'循环中。我不是Java专家吨,但可能你只需要将所有匹配添加到列表或者某物中。取决于你想用火柴做什么。 – pemistahl

+0

@Scorpion我的解决方案出现了一些错误。请看看更正后的版本。现在它按照您的预期工作。 – pemistahl

相关问题