廖雪峰Java9正则表达式-2正则表达式进阶-5非贪婪匹配

1.贪婪匹配

问题:给定一个字符串表示的数字,判断该数字末尾0的个数?

  • "123000": 3个0
  • "10100": 2个0
  • "1001": 0个0

先使用"^(\d+)(0*)$"匹配这三个字符串

public class Phone{
    public static void matchForZero(String s){
        Pattern pattern = Pattern.compile("(\\d+)(0*)$");
        Matcher matcher = pattern.matcher(s);
        if (matcher.matches()){
            System.out.print("第一组数:"+matcher.group(1)+"\t");
            System.out.println("第二组数:"+matcher.group(2));
        }
    }
}
public class PhoneTest {
   @Test
    public void testMatchForZero(){
        Phone.matchForZero("123000");
        Phone.matchForZero("10100");
        Phone.matchForZero("1001");
   }
}

廖雪峰Java9正则表达式-2正则表达式进阶-5非贪婪匹配
结果:0并未匹配到,group1将整个字符串完全匹配
原因:正则表达式默认使用贪婪匹配,尽可能多的向后匹配

2.非贪婪匹配

1中的解决方法:使用?实现非贪婪匹配
修改方法,再次运行

public class Phone{
    public static void matchForZero(String s){
        Pattern pattern = Pattern.compile("(\\d+?)(0*)$");// \d尽可能少的匹配,0尽可能多的匹配
        Matcher matcher = pattern.matcher(s);
        if (matcher.matches()){
            System.out.print("第一组数:"+matcher.group(1)+"\t");
            System.out.println("第二组数:"+matcher.group(2));
        }
    }
}

廖雪峰Java9正则表达式-2正则表达式进阶-5非贪婪匹配

3.区分非贪婪匹配与个数匹配

注意:?既能表示非贪婪匹配,也能表示0个或1个,所以要注意其含义

public class Phone{
    public static void matchForZero(String s){
        Pattern pattern = Pattern.compile("(\\d??)(9*)$");
        //第一个?表示0个或1个,可以匹配0或1个9
        //第二个?表示非贪婪匹配,尽可能少的匹配,两者综合,即匹配0个
        Matcher matcher = pattern.matcher(s);
        if (matcher.matches()){
            System.out.print("第一组数:"+matcher.group(1)+"\t");
            System.out.println("第二组数:"+matcher.group(2));
        }
    }
}
public class PhoneTest {
   @Test
    public void testMatchForZero(){
        Phone.matchForZero("9999");
   }
}

廖雪峰Java9正则表达式-2正则表达式进阶-5非贪婪匹配

4.代码示例

4.1贪婪匹配

ZeroCount.java

package com.testList;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ZeroCount {
    public static int zeros(String s){
        Pattern pattern = Pattern.compile("^\\d+(0*)$");
        Matcher matcher = pattern.matcher(s);
        if(matcher.matches()){
            String zeroStr = matcher.group(1);
            return zeroStr.length();
        }
        throw new IllegalArgumentException("Not a number");
    }
}

ZeroCountTest.java

package com.testList;

import org.junit.Test;

import static org.junit.Assert.*;

public class ZeroCountTest {

    @Test
    public void zeros() {
        assertEquals(0, ZeroCount.zeros("123456"));
        assertEquals(1, ZeroCount.zeros("123450"));
        assertEquals(2, ZeroCount.zeros("123400"));
        assertEquals(3, ZeroCount.zeros("123000"));
        assertEquals(4, ZeroCount.zeros("120000"));
        assertEquals(2, ZeroCount.zeros("100100"));
    }
}

廖雪峰Java9正则表达式-2正则表达式进阶-5非贪婪匹配

4.2非贪婪匹配

package com.testList;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ZeroCount {
    public static int zeros(String s){
        Pattern pattern = Pattern.compile("^\\d+?(0*)$");
        Matcher matcher = pattern.matcher(s);
        if(matcher.matches()){
            String zeroStr = matcher.group(1);
            return zeroStr.length();
        }
        throw new IllegalArgumentException("Not a number");
    }
}

廖雪峰Java9正则表达式-2正则表达式进阶-5非贪婪匹配

5.总结

  • 正则表达式匹配默认使用贪婪匹配
  • 使用?表示对某一规则进行非贪婪匹配
  • 注意区分?的含义 \d??
上一篇:JAVA9~16新功能概述


下一篇:AspectJ最终通知