正则表达式中的 ?
在正则表达式中,?既可以表示数量,0次或1次,等效于 {0,1},也可以作为特殊字符,表示其它含义。
(图片来源网络,侵删)
非贪心匹配
? 跟在其它数量限定符之后,表示非贪心匹配,即匹配时匹配搜索到的尽可能短的字符串。
下面来看一个例子:
@Test public void test() { Pattern pattern = Pattern.compile("a.*?"); Matcher matcher = pattern.matcher("abcabc"); if (matcher.matches()) { System.out.println(matcher.group()); } }
执行后输出:abcabc
不是最短匹配吗?为什么失灵了?
这其实牵涉到非贪心匹配的规则:非贪心匹配,到下一个规则前,匹配最短路径,如果没有下一个规则,按贪心匹配处理。
也就是说如果只出现 "a.*?" 还是按贪心匹配处理。
下面来看正确的使用:
@Test public void test() { Pattern pattern = Pattern.compile("(a.*?)(.*)"); Matcher matcher = pattern.matcher("afcafc"); if (matcher.matches()) { System.out.println(matcher.group(0)); System.out.println(matcher.group(1)); System.out.println(matcher.group(2)); } }
执行后输出:
afcafc a fcafc
可以看到,第一个捕获组捕获到了最短的字符串 "a",第二个捕获组捕获到了 "fcafc"。
下面再来看看另外两种情况:
- "(a.*)(.*)" 第一个捕获组会捕获所有,第二个不会报错,但什么也捕获不到
- "(a.*?)(.*?)" 第一个捕获组会捕获 "a",第二个捕获组会捕获 "fcafc",因为后面没有其它规则了,按贪心匹配处理。
匹配但不捕获 (?:pattern)
用在捕获组中,?: 放在正则表达式之前,表示匹配但不捕获,即通过 group 方法获取不到这一组匹配的值。
下面来看示例
@Test public void test0() { Pattern pattern = Pattern.compile("\\d{4}-(?:[a-z]+)"); Matcher matcher = pattern.matcher("3214-opo"); if (matcher.matches()) { System.out.println(matcher.group()); System.out.println(matcher.group(1)); // 报错 } }
通过 group(1) 进行捕获时会报错,即可以匹配,但不能捕获。若将 ?: 去掉,则通过 group(1) 可正常捕获。
开启单行模式 (?s)
(?s) 右侧开启单行模式,使 . 与任意字符匹配,包括换行符 \n。
下面来看示例:
private static final String DEFAULT_VARIABLE_PATTERN = "((?s).*)"; /** * 从输出结果可知,匹配到了换行符 '\n' */ @Test public void test4() { Pattern pattern = Pattern.compile(DEFAULT_VARIABLE_PATTERN); Matcher matcher = pattern.matcher("abc\nsdf"); if (matcher.matches()) { System.out.println(matcher.group()); System.out.println(matcher.group(1)); System.out.println(matcher.group(2)); // (?s) 不能作为捕获组,报错 } }
捕获时 (?s) 并不能作为捕获组来捕获,所以 "((?s).*)" 最大捕获到 group(1),捕获 group(2) 时报错。
@Test public void test5() { Pattern pattern = Pattern.compile("(.*)"); Matcher matcher = pattern.matcher("abc\nsdf"); if (matcher.matches()) { System.out.println(matcher.group()); System.out.println(matcher.group(1)); } }
去掉 (?s) 之后,再去匹配 "abc\nsdf",因为存在换行符,并不能匹配完成,所以什么也不会输出。
文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。