Java正则表达式学习(二)

    xiaoxiao2021-12-14  21

    Pattern & Matcher类

    Pattern类

    1.构造方法

    Pattern类用于创建一个正则表达式,也可以说创建一个匹配模式,它的构造方法是私有的,不可以直接创建,但可以通过Pattern.complie(String regex) 简单工厂方法(static 方法)创建一个正则表达式。例如:

    package month12.day2.regex; import java.util.regex.Pattern; /** * Created by Administrator on 2016/12/2. */ public class TestForPatternCompile { public static void main(String[] args) { Pattern p = Pattern.compile("\\s"); System.out.println(p.pattern()); //输出\s } }

    重载方法:public static Pattern compile(String regex, int flags) 关于flags的一些参数说明:

    编译标志效果Pattern.CANON_EQ当且仅当两个字符的”正规分解(canonical decomposition)”都完全相同的情况下,才认定匹配。比如用了这个标志之后,表达式”a/u030A”会匹配”?”。默认情况下,不考虑”规范相等性(canonical equivalence)”。Pattern.CASE_INSENSITIVE默认情况下,大小写不敏感的匹配只适用于US-ASCII字符集。这个标志能让表达式忽略大小写进行匹配。要想对Unicode字符进行大小不敏感的匹配,只要将UNICODE_CASE与这个标志合起来就行了。Pattern.COMMENTS在这种模式下,匹配时会忽略(正则表达式里的)空格字符(注:不是指表达式里的”\s”,而是指表达式里的空格,tab,回车之类)。注释从#开始,一直到这行结束。可以通过嵌入式的标志来启用Unix行模式。Pattern.DOTALL在这种模式下,表达式’.’可以匹配任意字符,包括表示一行的结束符。默认情况下,表达式’.’不匹配行的结束符。Pattern.MULTILINE在这种模式下,’^’和’$’分别匹配一行的开始和结束。此外,’^’仍然匹配字符串的开始,’$’也匹配字符串的结束。默认情况下,这两个表达式仅仅匹配字符串的开始和结束。Pattern.UNICODE_CASE在这个模式下,如果你还启用了CASE_INSENSITIVE标志,那么它会对Unicode字符进行大小写不明感的匹配。默认情况下,大小写不明感的匹配只适用于US-ASCII字符集。Pattern.UNIX_LINES在这个模式下,只有’\n’才被认作一行的中止,并且与’.’,’^’,以及’$’进行匹配。

    pattern()返回正则表达式的字符串形式,其实就是返回Pattern.complile(String regex)的regex参数

    2.成员方法

    1.public String[] split(CharSequence input)

    Pattern有一个split(CharSequence input)方法,用于分隔字符串,并返回一个String[],input为给定的字符串。例如:

    package month12.day2.Pattern; import java.util.regex.Pattern; /** * Created by Administrator on 2016/12/2. */ public class TestForSplit { public static void main(String args[]) { Pattern p = Pattern.compile("[,\\s]+"); String str[] = p.split("我的QQ号码是:1156405048 我的手机号是:17805938118" + " , 我的邮箱是adherersun@163.com"); for (int i = 0; i < str.length; i++) { System.out.println(str[i]); } } }

    程序运行结果: 重载方法:public String[] split(CharSequence input, int limit),limit表示把目标字符串最多分割成几段。

    2.public static boolean matches(String regex, CharSequence input)

    这是一个静态方法,用于用于快速匹配字符串,该方法适合用于只匹配一次,且匹配全部字符串。例如:

    package month12.day2.Pattern; import java.util.regex.Pattern; /** * Created by Administrator on 2016/12/2. */ public class TestForMatches { public static void main(String args[]) { System.out.println( Pattern.matches("\\d+","12345") ); //true System.out.println( Pattern.matches("\\d+","234aa") ); //false,需要整个字符串都匹配到,显然aa不满足条件 System.out.println( Pattern.matches("\\d+","22aa34") ); //false,需要整个字符串都匹配到,同样中间的aa不满足条件 } }
    3.public Matcher matcher(CharSequence input)

    public Matcher matcher(CharSequence input)用于返回一个Matcher实例对象,由于Matcher类的构造方法是默认访问权限的(即同包内才能访问),外部不能随意创建,只能通过public Matcher matcher(CharSequence input)方法得到该类的实例。 Pattern类只能做一些简单的匹配操作,要想得到更强更便捷的正则匹配操作,那就需要将Pattern与Matcher一起合作。Matcher类提供了对正则表达式的分组支持,以及对正则表达式的多次匹配支持。例如:

    package month12.day2.Pattern; import java.util.regex.*; /** * Created by Administrator on 2016/12/2. */ public class TestForMatcher { public static void main(String args[]) { Pattern p = Pattern.compile("\\d+"); Matcher matcher = p.matcher("12345aaa"); System.out.println( matcher.pattern() ); //返回p,也就是返回该Matcher对象是由哪个Pattern对象的创建的 } }

    Matcher类

    1.构造方法

    一个Matcher对象是一个状态机器(匹配器),它依据Pattern对象作为匹配模式对字符串展开匹配检查。首先一个Pattern实例订制了一个所用语法与perl(即Perl语言,内部集成了正则表达式则功能)的类似的正则表达式经编译后的模式,然后一个Matcher实例在这个给定的Pattern实例的模式控制下进行字符串的匹配工作。同样的,Matcher实例对象外部不能随意创建,因为其构造方法是默认访问权限的(default),只能通过Pattern的matcher()方法得到一个Matcher实例对象。(参考Pattern的第3点)

    2.成员方法

    1.public Pattern pattern()

    public Pattern pattern()用于返回创建此匹配器的模式。同样的,例子可参考Pattern的第3点。

    2.public Matcher usePattern(Pattern newPattern)

    public Matcher usePattern(Pattern newPattern)用于更改此 Matcher 用于查找匹配项的 Pattern。此方法可导致匹配器丢失有关最后发生匹配的组的信息。维持了输入中匹配器的位置并且不影响其最后添加的位置。例如:

    package month12.day2.Pattern; import java.util.regex.*; /** * Created by Administrator on 2016/12/2. */ public class TestForMatcher { public static void main(String args[]) { Pattern p = Pattern.compile("\\d+"); Pattern newP = Pattern.compile("\\s+"); Matcher matcher = p.matcher("12345aaa"); System.out.println( matcher.pattern() ); //返回p,也就是返回该Matcher对象是由哪个Pattern对象的创建 matcher.usePattern(newP); System.out.println( matcher.pattern() ); //返回newP,当前模式匹配Pattern对象已经更新 } }

    注意:如果 newPattern 为 null,将抛出IllegalArgumentException异常。

    3.public boolean find() & public boolean matches() & public boolean lookingAt()

    (1).public boolean find()对字符串进行匹配,匹配到的字符串可以在任何位置。如果该方法的前一次调用成功了并且从那时开始匹配器没有被重置,则从以前匹配操作没有匹配的第一个字符开始。即下一次匹配从以前匹配操作没有匹配的第一个字符开始。例如:

    package month12.day2.matcher; import java.util.regex.*; /** * Created by Administrator on 2016/12/2. */ public class TestForFind { public static void main(String args[]) { Pattern p=Pattern.compile("\\d+"); Matcher m=p.matcher("22bb23"); //返回true System.out.println( m.find() ); Matcher m2=p.matcher("aa2223"); //返回true System.out.println( m2.find() ); Matcher m3=p.matcher("aa2223bb"); //返回true System.out.println( m3.find() ); Matcher m4=p.matcher("aabb"); //返回false System.out.println( m4.find() ); } }

    (2).public boolean matches()对整个字符串进行匹配,只有整个字符串都匹配了才返回true。例如:

    package month12.day2.matcher; import java.util.regex.*; /** * Created by Administrator on 2016/12/2. */ public class TestForMatches { public static void main(String args[]) { Pattern p=Pattern.compile("\\d+"); Matcher m=p.matcher("2223"); //返回true System.out.println( m.matches() ); Matcher m2=p.matcher("aa2223"); //返回false,因为前面的aa不能被\d+匹配,导致整个字符串匹配不成功 System.out.println( m2.matches() ); Matcher m3=p.matcher("aa2223bb"); //返回false System.out.println( m3.matches() ); Matcher m4=p.matcher("aabb"); //返回false System.out.println( m4.matches() ); } }

    (3).lookingAt()对前面的字符串进行匹配,只有匹配到的字符串在最前面才返回true例如:

    package month12.day2.matcher; import java.util.regex.*; /** * Created by Administrator on 2016/12/2. */ public class TestForLookingAt { public static void main(String args[]) { Pattern p=Pattern.compile("\\d+"); Matcher m=p.matcher("22bb23"); //返回true System.out.println( m.lookingAt() ); Matcher m2=p.matcher("22aa2223"); //返回true System.out.println( m2.lookingAt() ); Matcher m3=p.matcher("aa2223bb"); //返回false,由于前面的aa不能匹配\d+ System.out.println( m3.lookingAt() ); Matcher m4=p.matcher("aabb22"); //返回false System.out.println( m4.lookingAt() ); } }
    4.public int start() & public int end() & public String group()

    当使用matches(),lookingAt(),find()执行匹配操作后,就可以利用以上三个方法得到更详细的信息。 start()返回匹配到的子字符串在字符串中的索引位置。 end()返回匹配到的子字符串的最后一个字符在字符串中的索引位置。实际上是匹配到的字符串的组的后一个字符串的索引位置。 group()返回匹配到的子字符串。 例如:

    package month12.day2.matcher.compare2; import java.util.regex.*; /** * Created by Administrator on 2016/12/2. */ public class TestForStartAndEnd { public static void main(String args[]) { Pattern p=Pattern.compile("\\d+"); Matcher m=p.matcher("aaa2223bb"); System.out.println( m.find() + " start at: " + m.start() + " end at: " + m.end() + " group: " + m.group()); Matcher m2=p.matcher("2223bb"); System.out.println( m2.lookingAt() + " start at: " + m2.start() + " end at: " + m2.end() + " group: " + m2.group()); Matcher m3=p.matcher("223344"); System.out.println( m3.matches() + " start at: " + m3.start() + " end at: " + m3.end() + " group: " + m3.group()); } }

    程序运行结果: 重载方法:start(),end(),group()均有一个重载方法它们是start(int i),end(int i),group(int i)专用于分组操作。Matcher类还有一个groupCount()用于返回Pattern模式匹配有多少组(()分组)。例如:

    package month12.day2.matcher.compare2; import java.util.regex.*; /** * Created by Administrator on 2016/12/2. */ public class TestForGroup { public static void main(String args[]) { Pattern p=Pattern.compile("([a-z]+)(\\d+)"); Matcher m=p.matcher("aaa2223bb"); System.out.println( m.find() ); //返回true,匹配aaa2223 System.out.println( m.groupCount() ); //返回2,因为有2组 System.out.println( m.start(1) ); //返回0 返回第一组匹配到的子字符串在字符串中的索引号 System.out.println( m.start(2) ); //返回3 System.out.println( m.end(1) ); //返回3 返回第一组匹配到的子字符串的最后一个字符在字符串中的索引位置. System.out.println( m.end(2) ); //返回7 System.out.println( m.group(1) ); //返回aaa,返回第一组匹配到的子字符串 System.out.println( m.group(2) ); //返回2223,返回第二组匹配到的子字符串 System.out.println( m.group(0) ); //返回aaa2223 //group0永远都表示整个与Pattern模式匹配的字符串,因此不参与分组计算 } }

    特别注意:只有当匹配操作成功,才可以使用start(),end(),group()三个方法,否则会抛出java.lang.IllegalStateException,也就是当matches(),lookingAt(),find()其中任意一个方法返回true时,才可以使用。

    补充:关于groupCount()的一点补充:

    package month12.day2.matcher; import java.util.regex.*; /** * Created by Administrator on 2016/12/2. */ public class TestForGroupCount { public static void main(String args[]) { Pattern p1 = Pattern.compile("\\d{3,5}"); Matcher m1 = p1.matcher("aaa2223bb"); System.out.println( m1.groupCount() ); //0 Pattern p2 = Pattern.compile("([a-z]+)(\\d+)"); Matcher m2 = p2.matcher("aaa2223bb"); System.out.println( m2.groupCount() ); //2 Pattern p3 = Pattern.compile("(([a-z]+)(\\d+))"); Matcher m3 = p3.matcher("aaa2223bb"); System.out.println( m3.groupCount() ); //3 } }

    一个简单的正则表达式找出字符串中的数字的例子:

    package month12.day2.matcher; import java.util.regex.*; /** * Created by Administrator on 2016/12/2. */ public class GetNumberSample { public static void main(String args[]) { Pattern p=Pattern.compile("\\d+"); Matcher m=p.matcher("我的QQ是:123456 我的电话是:0984290765 我的邮箱是:adherersun@163.com"); while(m.find()) { System.out.println(m.group()); System.out.print("start:"+m.start()); System.out.println(" end:"+m.end()); } } }

    程序运行结果: 每次执行匹配操作成功后start(),end(),group()三个方法的值都会改变,改变成匹配到的子字符串的信息,以及它们的重载方法,也会改变成相应的信息。

    5.public Matcher reset()

    public Matcher reset()的作用是重置匹配器,重置匹配器将放弃其所有显式状态信息并将其添加位置设置为零。匹配器的区域被设置为默认区域,默认区域就是其整个字符序列。例如:

    package month12.day2.matcher; import java.util.regex.*; /** * Created by Administrator on 2016/12/2. */ public class TestForReset { public static void main(String args[]) { Pattern p = Pattern.compile("\\d{3,5}"); String s = "123-34345-234-00"; Matcher m = p.matcher(s); System.out.println(m.find()+" start at:"+m.start()+" end at:"+m.end()); System.out.println(m.find()+" start at:"+m.start()+" end at:"+m.end()); m.reset(); System.out.println(m.find()+" start at:"+m.start()+" end at:"+m.end()); System.out.println(m.find()+" start at:"+m.start()+" end at:"+m.end()); } }

    程序运行结果: 上述结果说明:实例对象m reset()之后,以前匹配过的信息全部重置,重新开始从头匹配。 **重载方法public Matcher reset(CharSequence input) 重设该Matcher对象并且指定一个新的目标字符串。**

    6.public String replaceFirst(String replacement) & public String replaceAll(String replacement)

    String replaceAll(String replacement)将目标字符串里与既有模式相匹配的子串全部替换为指定的字符串 String replaceFirst(String replacement) 将目标字符串里第一个与既有模式相匹配的子串替换为指定的字符串。例如:

    package month12.day2.matcher; import java.util.regex.*; /** * Created by Administrator on 2016/12/2. */ public class TestForReplace { public static void main(String args[]) { Pattern p = Pattern.compile("\\d{3,5}"); String s = "123-34345-234-00"; Matcher m = p.matcher(s); System.out.println( m.replaceFirst("hello") ); //hello-34345-234-00 System.out.println( m.replaceAll("hello") ); //hello-hello-hello-00 } }
    7.public Matcher appendReplacement(StringBuffer sb, String replacement) & public StringBuffer appendTail(StringBuffer sb)

    appendReplacement(StringBuffer sb, String replacement)将当前匹配子串替换为指定字符串,并且将替换后的子串以及其之前到上次匹配子串之后的字符串段添加到一个StringBuffer对象里,而appendTail(StringBuffer sb)方法则将最后一次匹配工作后剩余的字符串添加到一个StringBuffer对象里。例如(这个在学习(一)中的小程序):

    import java.util.regex.*; public class RegexReplacement { public static void main(String[] args) throws Exception { Pattern pattern = Pattern.compile("cat"); Matcher matcher = pattern.matcher( "one cat, two cats in the yard"); StringBuffer sb = new StringBuffer(); while (matcher.find()) { matcher.appendReplacement(sb, "big $0"); } matcher.appendTail(sb); System.out.println(sb.toString()); } }

    程序运行结果: 对以上程序的解释: 字符串one cat, two cats in the yard,正则表达式模式为”cat”,第一次匹配后,cat子字符串与模式匹配,调用appendReplacement(sb,”big cat”),那么这时StringBuffer sb的内容为one big cat,也就是cat被替换为big cat并且与匹配子串前的内容加到sb里,而第二次匹配后调用appendReplacement(sb,”big cat”),那么sb的内容就变为one big cat,two big cats,如果最后再调用一次appendTail(sb),那么sb最终的内容将是one big cat, two big cats in the yard。 也可以在while循环中,对group(0)进行验证,while循环的代码可以改成如下:

    while (matcher.find()) { System.out.println(matcher.group(0)); matcher.appendReplacement(sb, "big $0"); }

    程序运行结果: 未完待续见Java正则表达式学习(三)

    转载请注明原文地址: https://ju.6miu.com/read-971358.html

    最新回复(0)