2012-08-09 40 views
4

我有以下模式定義:Java:如何使用Pattern類來提取表達式的片斷?

此正則表達式應該與表達這樣的:

  • 「週一至週五」
  • 「週二至週五,太陽」
  • 「星期一-Wed,Fri-Sun「

我在.NET中使用命名組非常容易,但是在Java中6我有點失落。任何人都可以向我展示一個代碼示例,它可以讓我提取日期,並準確理解給定表達式中提及的範圍和單日。

謝謝。

EDIT1

OK,這裏是我得到的檢查的m_daysRegex.matcher("Mon-Fri")組:

matchDays.groupCount() = 10 
matchDays.groups = [0,7,0,7,-1,-1,0,7,0,3,4,7,-1,...,-1] (22 values) 
matchDays.group(0) = "Mon-Fri" 
matchDays.group(1) = "Mon-Fri" 
matchDays.group(2) = null 
matchDays.group(3) = "Mon-Fri" 
matchDays.group(4) = "Mon" 
matchDays.group(5) = "Fri" 
matchDays.group(6) = null 
matchDays.group(7) = null 
matchDays.group(8) = null 
matchDays.group(9) = null 
matchDays.group(10) = null 

有人能向我解釋這一切的邏輯是什麼?我的意思是,我不僅應該得到「星期一」和「星期五」,而且還必須知道它們是範圍子表達式「星期一至星期五」的一部分,而不僅僅是「星期一,星期五」。

BTW,匹配 「週一,週五」 給了我們這樣的:

matchDays.groupCount() = 10 
matchDays.groups = [0,7,0,3,0,3,-1,-1,-1,-1,-1,-1,4,7,4,7,-1,...,-1] (22 values) 
matchDays.group(0) = "Mon,Fri" 
matchDays.group(1) = "Mon" 
matchDays.group(2) = "Mon" 
matchDays.group(3) = null 
matchDays.group(4) = null 
matchDays.group(5) = null 
matchDays.group(6) = "Fri" 
matchDays.group(7) = "Fri" 
matchDays.group(8) = null 
matchDays.group(9) = null 
matchDays.group(10) = null 

這是不同的,這是很好的。我仍然很難理解該算法。

在.NET中這很容易,所以我期待Java中的一些操作很簡單。公平,不是嗎?

EDIT2

是否有一個Java正則表達式指南解釋這個東西?到目前爲止,我看到的所有指南都檢查了非常簡單的正則表達式

EDIT3

OK,我開始明白這一點。我的正則表達式可以這樣描述:

(   // 1 = D1|D2-D3 
    (D1)|  // 2 = D1 
    (  // 3 = D2-D3 
    (D2)- // 4 = D2 
    (D3)  // 5 = D3 
) 
) 
(?:, 
    (  // 6 = D4|D5-D6 
    (D4)| // 7 = D4 
    (  // 8 = D5-D6 
    (D5)- // 9 = D5 
    (D6) // 10 = D6 
    ) 
) 
)* 

它解釋了「週一至週五」和「週一,週五」的組值。但是如何處理重複?例如,「星期一,星期三,星期五」?仍在試圖弄清楚。

EDIT4

我現在明白了。我可以匹配複雜的正則表達式,但我無法輕鬆提取各個匹配項 - 必須使用find()方法和更簡單的子正則表達式迭代。所以,在我的情況下,我決定:

  1. 匹配整個表達式,以確保它是有效的
  2. 分割它(與StringUtils.split從阿帕奇)用「」
  3. 迭代分裂部,分裂如有必要,按' - '。

感謝所有的善良撒瑪利亞人在那裏的所有幫助。

+1

我根本不會使用RegExp來解析這樣簡單的字符串。你想達到什麼目的?你只需要知道,如果字符串匹配「模式」,或者你需要「理解」字符串? – RoToRa 2012-08-10 11:24:46

回答

1

對於捕獲組等的描述,去這裏:http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html

至於你的模式,如果你寫的所有括號你:

((d)|((d)-(d)))(?:,((d)|((d)-(d))))* 

其中d是

Mon|Tue|... 

列出組,使用M來顯示屬於給定g的哪些部分roup:

0 - the matching string, if there is one 
1 - ((M)|((M)-(M)))(?:,((d)|((d)-(d))))* 
2 - ((M)|((d)-(d)))(?:,((d)|((d)-(d))))* 
3 - ((d)|((M)-(M)))(?:,((d)|((d)-(d))))* 
4 - ((d)|((M)-(d)))(?:,((d)|((d)-(d))))* 
5 - ((d)|((d)-(M)))(?:,((d)|((d)-(d))))* 
6 - ((d)|((d)-(d)))(?:,((M)|((M)-(M))))* 
7 - ((d)|((d)-(d)))(?:,((M)|((d)-(d))))* 
8 - ((d)|((d)-(d)))(?:,((d)|((M)-(M))))* 
9 - ((d)|((d)-(d)))(?:,((d)|((M)-(d))))* 
10 - ((d)|((d)-(d)))(?:,((d)|((d)-(M))))* 

鑑於字符串「週一至週五」你會得到你在輸出看到的字符串,即

0 - Mon-Fri i.e. the full match 
1 - Mon-Fri i.e. ((M)|((M)-(M))) 
2 - null i.e. not matched by (M) 
3 - Mon-Fri i.e. ((M)-(M)) 
4 - Mon i.e. the first (M) in group 3 
5 - Fri i.e. the second (M) in group 3 
6 - and so on... 

對於多場比賽,你會做這樣的事情

Matcher m = pattern.matcher(input); 
while (m.find()) { 
    // extract groups from m 
} 

編輯:想起來了,你可能並不需要最後一部分,即

(?:,((d)|((d)-(d))))* 

在你的模式。只需使用while循環與

(d)|((d)-(d)) 

模式來查找每個部分(即逗號之間的東西)。

+0

非常好,謝謝。但是重複呢?像「星期一,星期三,星期五」一樣? – mark 2012-08-10 11:17:23

+0

看我的編輯,例如在底部。 – claesv 2012-08-10 11:19:53

+0

它會匹配「Mon-FriblablablaWed-Thu」之類的東西嗎?第一個find()會匹配「Mon-Fri」和下一個 - 「Wed-Thu」,允許它們之間的垃圾,不是嗎? – mark 2012-08-10 11:39:46

0

java中的正則表達式組使用索引訪問,索引是左括號的計數器。

這裏是一個例子(我以前的工作),它適用於java中的組。希望這可以幫助。

/** 
* <li>range={0,2} -&gt; 0 to 2 
* <li>range={3,n} -&gt; 3 to Integer.MAX_VALUE 
* <li>range={7} -&gt; 0 to 7 
* <li>range={n} -&gt; 0 to Integer.MAX_VALUE 
* <li>range={-n} -&gt; Integer.MIN_VALUE to 0 
*/ 
@Test 
public void getRange() { 
    Pattern p = Pattern.compile(
     "\\{" + 
     "([+-]?(n|[0-9])){1}" + // group 1 
     "(" + 
     "(,){1}" + 
     "([+-]?(n|[0-9])){1}" + // group 5 
     "){0,1}" + 
     "\\}"); 

    Matcher m = null; 
    String range = null; 

    logger.debug("pattern: " + p.pattern()); 

    range = "{0,2}"; 
    m = p.matcher(range); 
    logger.debug(range + " -> groupCout: " + m.groupCount()); 
    printGroups(m); 
    Assert.assertEquals("0", m.group(1)); 
    Assert.assertEquals("2", m.group(5)); 

    range = "{3,n}"; 
    m = p.matcher(range); 
    logger.debug(range + " -> groupCout: " + m.groupCount()); 
    printGroups(m); 
    Assert.assertEquals("3", m.group(1)); 
    Assert.assertEquals("n", m.group(5)); 

    range = "{7}"; 
    m = p.matcher(range); 
    logger.debug(range + " -> groupCout: " + m.groupCount()); 
    printGroups(m); 
    Assert.assertEquals("7", m.group(1)); 
    Assert.assertEquals(null, m.group(5)); 

    range = "{n}"; 
    m = p.matcher(range); 
    logger.debug(range + " -> groupCout: " + m.groupCount()); 
    printGroups(m); 
    Assert.assertEquals("n", m.group(1)); 
    Assert.assertEquals(null, m.group(5)); 

    range = "{-3,-7}"; 
    m = p.matcher(range); 
    logger.debug(range + " -> groupCout: " + m.groupCount()); 
    printGroups(m); 
    Assert.assertEquals("-3", m.group(1)); 
    Assert.assertEquals("-7", m.group(5)); 
} 

private void printGroups(Matcher m) { 
    if(m != null && m.matches()) { 
     for(int i = 0; i < m.groupCount()+1; i++) { 
      logger.debug("group " + i + ": " + m.group(i)); 

     } 
    } 
} 
+1

你的表情太簡單 - 它們既不包含重複也不包含變化。我很抱歉,但我無法學習它。 – mark 2012-08-10 10:41:40

+1

我不/不知道你是否可以學習,但我認爲它回答了你的問題,關於在java正則表達式中處理'groups並且希望有一個'example'。例子應該很簡單。是不是你最終做了什麼...通過索引訪問goups?修辭問題... – A4L 2012-08-10 17:20:47