• 正则表达式中的 ?


    正则表达式中,?既可以表示数量,0次或1次,等效于 {0,1},也可以作为特殊字符,表示其它含义。

    非贪心匹配

    ? 跟在其它数量限定符之后,表示非贪心匹配,即匹配时匹配搜索到的尽可能短的字符串

    下面来看一个例子:

    1. @Test
    2. public void test() {
    3. Pattern pattern = Pattern.compile("a.*?");
    4. Matcher matcher = pattern.matcher("abcabc");
    5. if (matcher.matches()) {
    6. System.out.println(matcher.group());
    7. }
    8. }

    执行后输出:abcabc

    不是最短匹配吗?为什么失灵了?

    这其实牵涉到非贪心匹配的规则:非贪心匹配,到下一个规则前,匹配最短路径,如果没有下一个规则,按贪心匹配处理。

    也就是说如果只出现 "a.*?" 还是按贪心匹配处理。

    下面来看正确的使用:

    1. @Test
    2. public void test() {
    3. Pattern pattern = Pattern.compile("(a.*?)(.*)");
    4. Matcher matcher = pattern.matcher("afcafc");
    5. if (matcher.matches()) {
    6. System.out.println(matcher.group(0));
    7. System.out.println(matcher.group(1));
    8. System.out.println(matcher.group(2));
    9. }
    10. }

    执行后输出:

    1. afcafc
    2. a
    3. fcafc

    可以看到,第一个捕获组捕获到了最短的字符串 "a",第二个捕获组捕获到了 "fcafc"。

    下面再来看看另外两种情况:

    • "(a.*)(.*)"  第一个捕获组会捕获所有,第二个不会报错,但什么也捕获不到
    • "(a.*?)(.*?)"  第一个捕获组会捕获 "a",第二个捕获组会捕获 "fcafc",因为后面没有其它规则了,按贪心匹配处理。

    匹配但不捕获 (?:pattern) 

    用在捕获组中,?: 放在正则表达式之前,表示匹配但不捕获,即通过 group 方法获取不到这一组匹配的值。

    下面来看示例

    1. @Test
    2. public void test0() {
    3. Pattern pattern = Pattern.compile("\\d{4}-(?:[a-z]+)");
    4. Matcher matcher = pattern.matcher("3214-opo");
    5. if (matcher.matches()) {
    6. System.out.println(matcher.group());
    7. System.out.println(matcher.group(1)); // 报错
    8. }
    9. }

    通过 group(1) 进行捕获时会报错,即可以匹配,但不能捕获。若将 ?: 去掉,则通过 group(1) 可正常捕获。

    开启单行模式 (?s)

    (?s) 右侧开启单行模式,使 . 与任意字符匹配,包括换行符 \n。

    下面来看示例:

    1. private static final String DEFAULT_VARIABLE_PATTERN = "((?s).*)";
    2. /**
    3. * 从输出结果可知,匹配到了换行符 '\n'
    4. */
    5. @Test
    6. public void test4() {
    7. Pattern pattern = Pattern.compile(DEFAULT_VARIABLE_PATTERN);
    8. Matcher matcher = pattern.matcher("abc\nsdf");
    9. if (matcher.matches()) {
    10. System.out.println(matcher.group());
    11. System.out.println(matcher.group(1));
    12. System.out.println(matcher.group(2)); // (?s) 不能作为捕获组,报错
    13. }
    14. }

    捕获时 (?s) 并不能作为捕获组来捕获,所以 "((?s).*)" 最大捕获到 group(1),捕获 group(2) 时报错。

    1. @Test
    2. public void test5() {
    3. Pattern pattern = Pattern.compile("(.*)");
    4. Matcher matcher = pattern.matcher("abc\nsdf");
    5. if (matcher.matches()) {
    6. System.out.println(matcher.group());
    7. System.out.println(matcher.group(1));
    8. }
    9. }

    去掉 (?s) 之后,再去匹配 "abc\nsdf",因为存在换行符,并不能匹配完成,所以什么也不会输出。
     

  • 相关阅读:
    数据结构--哈希表(Hash Table)
    【AIGC专题】Stable Diffusion 从入门到企业级实战0601
    Kotlin(七) 接口
    day14网络编程
    zoj 1589 Professor John
    我想咨询一下Python,请问在哪儿找资源比较好呀?
    【Spring事务的实现原理】
    nacos和eruka的区别
    项目实战(依旧还是登录认证,JWT解析异常处理,授权信息处理)
    医院信息化的三种演进建设模式
  • 原文地址:https://blog.csdn.net/zlk252620068/article/details/140274876