Java正则Pattern的find()与matches()匹配分组差异问题
问题原因分析
1. find()和matches()的本质区别
matches()要求整个输入字符串完全符合正则规则,不管可选分组有没有匹配内容,只要整串能对应上就会成功。find()是在字符串里找任意一段符合规则的子串,不要求覆盖整串。要是你的正则没加^(字符串开头)和$(字符串结尾)这两个锚点,它很可能只匹配输入的一部分,而不是你想要的完整内容。
2. 可选分组(?:\n.+)?的坑
(1)默认.不认识换行符
Java正则默认不会让.匹配换行符,除非你开了Pattern.DOTALL模式。(?:\n.+)?的逻辑是匹配“换行+任意非换行字符”,但如果输入是单行(没冗余文本),这个分组就会匹配空。但要是正则没加锚点,find()可能会瞎匹配——比如只抓到SL:这部分,漏了后面的数值,自然抓不到分组内容。
(2)贪婪/非贪婪改了也白改
你试的(?:\n.+?)?非贪婪模式没用,因为这个分组本身就是可选的(末尾的?)。没冗余文本的时候,不管贪婪还是非贪婪,它都会匹配空,根本影响不到前面的匹配逻辑——问题根本不在这儿。
3. 抓不到数值的直接原因
要是find()能匹配到SL行但抓不到数值,十有八九是这几种情况:
- 正则写错了,把数值的捕获组放到可选分组里了;
- 没加锚点,
find()匹配到了不含数值的子串(比如只匹配SL:); - 正则的优先级有问题,引擎优先匹配可选分组,跳过了前面的捕获组。
解决办法
- 给正则加上
^和$锚点,强制find()匹配完整字符串,和matches()逻辑对齐:^SL:(\d+)(?:\n.+)?$; - 要是需要支持多行冗余文本,开
Pattern.DOTALL模式,把正则改成^SL:(\d+)(?:\s+.+)?$(用\s+匹配任意空白/换行,更灵活); - 调试的时候打印
Matcher.group(0)(完整匹配内容)和group(1)(抓的数值),看看实际匹配到了啥,一目了然。
内容的提问来源于stack exchange,提问作者Kannan J
相关产品推荐
相关产品推荐

