2015-03-13 19 views
1

我試圖從HTML代碼片段中獲取第一段內容...沒有什麼更容易,是吧?但由於某些原因,.*?運營商似乎工作貪婪:Java中的正則表達式運算符似乎始終工作貪婪

import java.util.regex.Matcher; 
import java.util.regex.Pattern; 

public class test 
{ 
    public static void main(String[] args) 
    { 
     Pattern regex = Pattern.compile("<p(?: [^>]*)?>(.*?)</p>", Pattern.DOTALL); 
     Matcher match = regex.matcher("<p class=\"baz\">foo</p> <p>bar</p>"); 
     System.out.println(match.matches()); 
     System.out.println(match.group(1)); 
    } 
} 

我預計第一款(foo)只是內容相匹配,但這裏是結果:

$ javac test.java && java test 
true 
foo</p> <p>bar 

任何理由.*?繼續比賽後首先</p>

+0

它在這裏工作https://regex101.com/r/oC3qA3/5 – 2015-03-13 11:27:03

+2

嘗試更換'的System.out.println( match.matches());'用'System.out.println(match.find());' – npinti 2015-03-13 11:29:04

+0

@npinti你爲什麼這麼說? – 2015-03-13 11:29:54

回答

4

正如npinti in the comments所解釋的,問題是由致電match.match()造成的。這會嘗試將您的模式與整個輸入字符串進行匹配。只有當正則表達式引擎找到某種方式將字符串表示爲模式的實例時,它纔會成功。達到此目的的唯一方法是匹配(.*?)foo</p> <p>bar

有兩種方法來解決這個問題:

  1. 最簡單的就是切換到match.find()。這會在字符串中找到您的模式的第一個匹配項。由於不需要整個字符串匹配,所以非貪婪量詞可以確保您根據需要獲得foo

  2. 調整您的模式以匹配整個字符串。即"<p(?: [^>]*)?>(.*?)</p>.*"


不可避免的,但是,這些 「簡單」 的計劃來解析一些HTML grow more and more unwieldy as requirements change。用類似JSoup的方式解析HTML真的很簡單。切換到現在,不要回頭。看看它是多麼容易:

Document doc = Jsoup.parseBodyFragment("<p class=\"baz\">foo</p> <p>bar</p>"); 
Elements paragraphs = doc.getElementsByTag("p"); 

if (paragraphs.size() > 0) { 
    System.out.println(paragraphs.get(0).text()); 
} 

打印:foo

+0

謝謝你提供的所有提示,將調查JSoup,但現在只需使用find()修復代碼。 – 2015-03-13 11:41:27

+2

@RafałWrzeszcz:根據建議堅持JSoup。將爲您節省很多麻煩int他的未來 – npinti 2015-03-13 11:41:59

+0

@RafałWrzeszcz我已經添加了一個JSoup例子,它比正則表達式要容易得多... – 2015-03-13 13:28:04

3

對不起,沒有發佈此更早,沒有訪問Java環境。

問題是,matches()會嘗試匹配整個字符串。意思是它會隱含地加上^$。與find()更換matches()應該解決這個問題:

Pattern regex = Pattern.compile("<p(?: [^>]*)?>(.*?)</p>", Pattern.DOTALL); 
    Matcher match = regex.matcher("<p class=\"baz\">foo</p> <p>bar</p>"); 
    System.out.println(match.find()); 
    System.out.println(match.group(1)); 

產量:

true 
foo 
+0

Ahah,我不確定你會發佈一個答案,我會離開我的,因爲它有更多的細節,但是爲了解決這個問題我投票贊成! – 2015-03-13 11:41:48

+0

@Duncan:你的回答比較好,因爲你提倡'JSoup'(你應該如何處理HTML解析)。從我這裏得到了讚賞。 – npinti 2015-03-13 11:43:02