捕获组可以通过从左到右计算其开括号来编号。例如,在表达式 ((A)(B(C))) 中,存在四个这样的组:
1 ((A)(B(C)))
2 (A)
3 (B(C))
4 (C)
每一个“()”是一个捕获组,组零($0)始终代表整个表达式
Pattern pattern = Pattern.compile(reg);
Matcher matcher = pattern.matcher(data);
while (matcher.find()) {
for (int i = 0; i <= matcher.groupCount(); i++) {
matcher.group(i);//读捕获组
}
}
使用正则表达式可以使用“$数字”来表示捕获组
测试
如:"abc 123".replaceAll("(\\w+)\\s+(\\d+)","$2-$1");
输出:123-abc
非捕获,即不会当做一个捕获组
(?:X) X,作为非捕获组
(?idmsux-idmsux) Nothing,但是将匹配标志由 on 转为 off
(?idmsux-idmsux:X) X,作为带有给定标志 on - off 的非捕获组
(?=X) X,通过零宽度的正 lookahead
(?!X) X,通过零宽度的负 lookahead
(?<=X) X,通过零宽度的正 lookbehind
(?X) X,作为独立的非捕获组
//(?:a)(\\d{3})代表着这样的功能:
//查找给出的字符串中符合a后面有三个数字的这样的字符串,当然取得的子串不包括"a"
Pattern pattern = Pattern.compile("(?:a)(\\d{3})");
Matcher matcher = pattern.matcher("a444b666c888a999");
while (matcher.find()) {
for (int i = 0; i <= matcher.groupCount(); i++) {
System.out.println("group" + i + ": " + matcher.group(i));
}
}
(?:a),不会当作一个捕获组,输出结果:
group0: a444
group1: 444
group0: a999
group1: 999
(?i): 默认情况下,不区分大小写的匹配假定仅匹配 US-ASCII 字符集中的字符。可以通过指定 UNICODE_CASE 标志连同此标志来启用 Unicode 感知的、不区分大小写的匹配。
(?d): 启用 Unix 行模式。在此模式中,.、^ 和 $ 的行为中仅识别 ‘\n’ 行结束符。
(?m): 启用多行模式。
在多行模式中,表达式 ^ 和 $ 仅分别在行结束符前后匹配,或者在输入序列的结尾处匹配。默认情况下,这些表达式仅在整个输入序列的开头和结尾处匹配。
(?s): 启用 dotall 模式。
在 dotall 模式中,表达式 . 可以匹配任何字符,包括行结束符。默认情况下,此表达式不匹配行结束符。
(?u): 启用 Unicode 感知的大小写折叠。
指定此标志后,由 CASE_INSENSITIVE 标志启用时,不区分大小写的匹配将以符合 Unicode Standard 的方式完成。默认情况下,不区分大小写的匹配假定仅匹配 US-ASCII 字符集中的字符。
(?x) : 模式中允许空白和注释。
此模式将忽略空白和在结束行之前以 # 开头的嵌入式注释。
忽略大小写示例
Pattern pattern = Pattern.compile("(?i)[A-Z]\\d{3}");
Matcher matcher = pattern.matcher("a444b666c888a999");
while (matcher.find()) {
for (int i = 0; i <= matcher.groupCount(); i++) {
System.out.println("group" + i + ": " + matcher.group(i));
}
}
表达式前后检查关系;
lookahea在简单粗暴的理解就是:(?=X)与(?!X)前面需要有一个表达式才能生效
lookbehind就是:(?<=X)与(?
Pattern pattern = Pattern.compile("\\d{3}(?=a)");
Matcher matcher = pattern.matcher("a444b666c888a999");
while (matcher.find()) {
System.out.println(matcher.group());
}
\\d{3}(?=a)查找给出的字符串中符合a前面有三个数字的这样的字符串,只取出3个数字,不包括a
输出结果:888
如果把表达式 \\d{3}(?=a)换成(?=a)\\d{3},无法匹配到任务内容
Pattern pattern = Pattern.compile("\\d{3}(?!a)");
Matcher matcher = pattern.matcher("a444b666c888a999");
while (matcher.find()) {
System.out.println(matcher.group());
}
\\d{3}(?!a)代表着连续三个数字的后面出现的字符不是a的匹配,
输出结果:
444
666
999
Pattern pattern = Pattern.compile("(?<=a)\\d{3}");
Matcher matcher = pattern.matcher("a444b666c888a999");
while (matcher.find()) {
System.out.println(matcher.group());
}
(?<=a)\\d{3}代表着a后面是连续三个数字出现的字符的匹配,
输出结果:
444
999
Pattern pattern = Pattern.compile("(?
behind 和 head 是说“目标/待查找字符串”的位置,正/负是条件字符串出现与否。 (?<=X)与(? 和 (?=X)与(?!X)
刚好成对,一个在前一个在后,一个包含一个不包含。
(?:X)的作用是取消分组,但grup(0)时仍然包含该组的内容。
非捕获组,其实这个对结果不影响的,只是说你这个括号不是分组,只是为了吧一段规则包含起来。
因为保存分组需要时间和内存。使用非捕获组可以提升性能。
https://www.regular-expressions.info/lookaround.html
http://jszx-jxpt.cuit.edu.cn/JavaAPI/java/util/regex/Pattern.html#cg
https://blog.csdn.net/lsp1991/article/details/47974785