Java 此正则表达式捕获的组数错误

Java 此正则表达式捕获的组数错误,java,android,regex,Java,Android,Regex,我必须解析字符串并捕获一些值: 频率=每周;WKST=MO;BYDAY=2TU,2WE 我想捕捉两组: 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}),?)*.*")

我必须解析字符串并捕获一些值:

频率=每周;WKST=MO;BYDAY=2TU,2WE

我想捕捉两组:

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);
        ...
    }
}

我有点生疏了,但我会提出“警告”。首先,regexp有多种方言。关于这一点,有一本很棒的O'Reilly书,但是你的C#实用程序可能会应用稍微不同的规则

作为一个例子,我使用了一个类似(但不同)的方法,并发现它确实解析了不同的东西

首先,它拒绝了您的regexp(可能是输入错误?),除非在它前面加一个点(.),否则首字母“*”没有意义。像这样:

.*;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


也许这会有所帮助?

您也可以使用这种方法来提高可读性,并在某种程度上独立于使用更常见的regexp子集的实现

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));
    }
}

您的正则表达式在Java中的工作方式与在C#中的工作方式相同,只是在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]);
}

THX-是的,有一个复制和过去的错误-你关于初始正则表达式的假设是正确的-我会更新我的问题。但是:我理解你的正则表达式的方式是,它假设总是有两个工作日部分。但是1到6是允许的(或者0到7,但这没有意义)。我需要捕获一个具有时间间隔的工作日变量计数。就像代码示例与RegExWB示例一样。具体来说,这个RegEx应该使用Java.util.RegEx.Pattern方言:不幸的是,这不适用于第二种情况:“FREQ=WEEKLY;WKST=MO;BYDAY=22TU,-2WE,+223FR”我不确定Java中有哪些工具可用于完成您需要的任务ed,但一个线索是您的正则表达式只有两个捕获组:
([+-]?[0-9]*)
([A-Z]{2})
是的-是的。一个用于间隔,一个用于工作日。在C#(.net)中当一个正则表达式有更多的命中率时,我会在我的捕获组中得到一系列结果。就像在RegExWB示例中一样。第1组有三个命中率,第2组也有。Java也可以这样做吗?啊哈-我想这就是我要找的。我明天会试试,现在我会得到一个比萨饼和一杯啤酒。现在是晚上了…非常好用!谢谢!find()是我错过的东西。
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]);
}