我试图用Java捕获嵌套的可选组,但它没有用完。
我尝试捕获关键字后跟一个间隔,其中关键字现在是任何东西,间隔只是两个日期。间隔可以是可选的,并且两个日期也可以是可选的。所以,以下是有效的匹配。
我想捕获关键字和两个日期,即使它们为空。
这是我提出的Java MWE。
public class Parser {
public static void main(String[] args) {
Parser parser = new Parser();
String s = "word [01/01/1900, 01/01/2000]";
parser.parse(s);
}
public void parse(String s) {
String date = "\\d{2}/\\d{2}/\\d{4}";
String interval = "\\[("+date+")?, ("+date+")?\\]";
String keyword = "(.+)( "+interval+")?";
Pattern p = Pattern.compile(keyword);
Matcher m = p.matcher(s);
if (m.matches()) {
for (int i = 0; i <= m.groupCount(); ++i) {
System.out.println(i + ": " + m.group(i));
}
}
}
}
这是输出
0: word [01/01/1900, 01/01/2000]
1: word [01/01/1900, 01/01/2000]
2: null
3: null
4: null
如果间隔不是可选的,那么它可以正常工作。
String keyword = "(.+)( "+interval+")";
0: word [01/01/1900, 01/01/2000]
1: word
2: [01/01/1900, 01/01/2000]
3: 01/01/1900
4: 01/01/2000
如果interval是不匹配的组(但仍然是可选的),那么它就不起作用。
String keyword = "(.+)(?: "+interval+")?";
0: word [01/01/1900, 01/01/2000]
1: word [01/01/1900, 01/01/2000]
2: null
3: null
我需要做什么才能找回这两个日期?谢谢。
编辑:第2部分。
假设现在我注意匹配重复的关键字。即正则表达式,keyword(, keyword)*
。我尝试了这个,但只捕获了第一个和最后一个实例。
为简单起见,假设我想将以下a, b, c, d
与正则表达式([a-z])(?:, ([a-z]))*
匹配
但是,我只能找回第一组和最后一组。
0: a, b, c, d
1: a
2: d
为什么会这样?
刚刚发现无法做到这一点。 Capture group multiple times
答案 0 :(得分:0)
将keyword
的第一部分从(.+)
更改为(.+?)
。
如果没有?
,则(.+)
是贪心量词。这意味着它将尝试尽可能多地匹配。我不知道正则表达式引擎是如何工作的所有机制,但我相信在你的情况下,它所做的是将一些计数器N
设置为源中剩余的字符数。如果它可以消耗那么多的字符并使整个正则表达式匹配,它就会。否则,它会尝试N-1
,N-2
等,直到整个正则表达式匹配为止。在尝试这个时,我也认为它从左到右;也就是说,因为(.+)
是最左边的&#34;部分&#34;对于模式(对于&#34; part&#34;的某些定义),它在尝试对右边的部分进行任何循环之前在该部分上循环。因此,使(.+)
贪婪比使模式的任何其他部分贪婪更重要; <{1}}优先。
在你的情况下,由于(.+)
后跟一个可选部分,正则表达式匹配器首先尝试字符串的整个剩余部分 - 并且它成功,因为字符串的其余部分是空的,是可选子字符串的精确匹配。这也应该解释为什么如果您的子字符串不可选,它不起作用 - 空子字符串不再匹配。
添加(.+)
使其成为&#34;不情愿的&#34; (或&#34;吝啬&#34;)量词,其工作方向相反。首先看看它是否可以匹配0个字符,然后是1,2,......,而不是从N开始向下。因此,当它达到5,匹配?
时,它会发现字符串的其余部分与您的可选部分匹配,它会完成并提供您期望的结果。