2010-02-18 43 views
2

我解析字符串,並捕捉一些值:這正則表達式捕獲錯誤的號碼組

FREQ = WEEKLY; WKST = MO; BYDAY = 2TU,2WE

我想捕捉2組:

grp 1: 2, 2 
grp 2: TU, WE 

數字代表間隔。恩,我們代表工作日。我需要兩個。

我使用這個代碼:

private final static java.util.regex.Pattern regBYDAY = java.util.regex.Pattern.compile(".*;BYDAY=(?:([+-]?[0-9]*)([A-Z]{2}),?)*.*"); 

String rrule = "FREQ=WEEKLY;WKST=MO;BYDAY=2TU,2WE"; 
java.util.regex.Matcher result = regBYDAY.matcher(rrule); 
if (result.matches()) 
{ 
    int grpCount = result.groupCount(); 
    for (int i = 1; i < grpCount; i++) 
    { 
     String g = result.group(i); 
     ... 
    } 
} 

grpCount == 2 - 爲什麼?如果我正確地閱讀了java文檔(這一點),我應該得到5? 0 =整個表達式,1,2,3,4 =我的截圖2,2,TU和WE。

result.group(1)==「2」;

我是一個C#程序員,擁有很少的Java經驗,所以我在「正則表達式工作臺」中測試了RegEx--一個用於測試RegEx的出色C#程序。我的RegEx工作正常。

https://code.msdn.microsoft.com/RegexWorkbench

RegExWB:

.*;BYDAY=(?:([+-]?[0-9]*)([A-Z]{2}),?)*.* 

Matching: 
FREQ=WEEKLY;WKST=MO;BYDAY=22TU,-2WE,+223FR 
    1 => 22 
    1 => -2 
    1 => +223 
    2 => TU 
    2 => WE 
    2 => FR 
+0

我不知道是什麼工具在java中可以滿足你的需求,但是一個線索是你的正則表達式只有2個捕獲組:'([+ - ]?[0-9] *)'和'([AZ] {2})' – Johrn 2010-02-18 18:59:57

+0

是的 - 那是真的。一個用於間隔,一個用於平日。在C#(.net)中,當正則表達式有更多的命中時,我會在我的捕獲組中獲得一個結果數組。就像在RegExWB示例中一樣。第1組有三個命中,第2組也有。這也可以用Java? – Arthur 2010-02-18 19:04:12

回答

1

您也可以使用這種方法來增加可讀性,達到某一點自主創新結采用了更爲常見的正則表達式的子集

final Pattern re1 = Pattern.compile(".*;BYDAY=(.*)"); 
final Pattern re2 = Pattern.compile("(?:([+-]?[0-9]*)([A-Z]{2}),?)"); 

final Matcher matcher1 = re1.matcher(rrule); 
if (matcher1.matches()) { 
    final String group1 = matcher1.group(1); 
    Matcher matcher2 = re2.matcher(group1); 
    while(matcher2.find()) { 
     System.out.println("group: " + matcher2.group(1) + " " + 
        matcher2.group(2)); 
    } 
} 
+0

Ahhhh - 我想這就是我要找的。我明天會嘗試,現在我會拿比薩啤酒。這是傍晚在這裏...... – Arthur 2010-02-18 19:27:14

+0

完美的作品!謝謝! find()是我錯過的東西。 – Arthur 2010-02-19 08:47:27

0

我有點生疏,但我會提出 「警告」。首先,正則表達式(s)有各種方言。有一本非常棒的O'Reilly關於這本書的書,但是您的C#實用程序有可能應用稍微不同的規則。

舉個例子,我使用了一個類似(但不同tool),發現它確實解析東西differenty ...

首先它拒絕了你的正則表達式(可能是筆誤?)最初的「*」沒有意義,除非你在它前面放一個點(。)。就像這樣:

.*;BYDAY=(?:([+-]?[0-9]*)([A-Z]{2}),?)*.* 

現在,它被接受,但 「匹配」 只有2/WE的一部分, 「跳過」 了2/TU對。

(我建議你閱讀關於貪婪和非貪婪匹配明白這一點更好

所以我更新了你的模式如下:

.*;BYDAY=(?:([+-]?[0-9]*)([A-Z]{2}),?),(?:([+-]?[0-9]*)([A-Z]{2}),?)*.* 

而現在它的工作原理和正確捕獲2 ,TU,2和WE。

也許這可以幫助?

+0

THX - 是的,有一個複製和過去的錯誤 - 你對最初的RegEx的假設是正確的 - 我會更新我的問題。 但是:我理解你的RegEx的方式,它會假設,總是有兩個工作日的部分。但允許1到6(或0到7,但沒有意義)。我需要用間隔記錄週日變數。像代碼示例與RegExWB示例一樣。 – Arthur 2010-02-18 18:42:58

+0

具體而言,此RegEx應使用Java java.util.regex.Pattern方言:http://java.sun.com/javase/6/docs/api/java/util/regex/Pattern.html – Powerlord 2010-02-18 18:58:48

+0

不幸的是,不適用於你的第二種情況:'FREQ = WEEKLY; WKST = MO; BYDAY = 22TU,-2WE,+ 223FR' – 2010-02-18 19:06:15

1

你的正則表達式的作品在Java中一樣,它在C#中確實從實現ndence;只是在Java中,您只能訪問每個組的最終捕獲。事實上,.NET是我所知道的兩種正則表達式之一,可以讓你檢索中間捕獲(Perl 6是另一種)。

這可能是你想要的東西在Java中最簡單的方式:你有興趣

String s= "FREQ=WEEKLY;WKST=MO;BYDAY=22TU,-2WE,+223FR"; 
Pattern p = Pattern.compile("(?:;BYDAY=|,)([+-]?[0-9]+)([A-Z]{2})"); 
Matcher m = p.matcher(s); 
while (m.find()) 
{ 
    System.out.printf("Interval: %5s, Day of Week: %s%n", 
        m.group(1), m.group(2)); 
} 

下面是等價的C#代碼,以防:

string s = "FREQ=WEEKLY;WKST=MO;BYDAY=22TU,-2WE,+223FR"; 
Regex r = new Regex(@"(?:;BYDAY=|,)([+-]?[0-9]+)([A-Z]{2})"); 
foreach (Match m in r.Matches(s)) 
{ 
    Console.WriteLine("Interval: {0,5}, Day of Week: {1}", 
        m.Groups[1], m.Groups[2]); 
}