2013-01-03 178 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

相關問題