本篇是Java编程思想第四版的正则表达式笔记,因为正则表达式语法很容易忘记,自己整理整理。感觉好多。。还没写完
正则表达式是一种强大而灵活的文本处理工具。通过正则表达式,我们可以构造一个复杂的文本模式,对输入的字符串进行搜索,一旦找到了匹配这些模式的部分(就是找到了你想要找的字符串),你就可以随心所欲地处理了。
可以参考JDK文档的java.util.regex包中的Pattern类,我将其书上列出的放在文章最后面
1. matches
引用正则表达式最简单的途径就是利用String类的matches方法,但是要注意的是这里是全字符串匹配
String str1 = "How are you?";
System.out.println(str1.matches("you")); //flase
System.out.println(str1.matches("How are you")); //ture
这里我一开始就觉得很奇怪,为什么不能匹配一个确切的单词呢,后来发现了一篇博客,才知道原来它会在原来的基础上自动加上^和$(这两个都是边界匹配符表示一行的起始和结束),这样就变成匹配整个字符串了
如果想要找某个单词,可以这么写
System.out.println("How are you?".matches(".*(are)*"));
点可以匹配任意一个字符,are要括号起来表示一个整体。
数字字符串
System.out.println("+3254".matches("(-|\\+)?\\d+")); //true
这里\\表示转义,\\+表示+号字符,不转移表示重复前面的内容一个或多个,| 表示或者,\d表示就是0-9字符,问号表示重复前面内容的0次或一次,也就是要么不出现,要么出现一次。这都是最后面表中的量词
2. split方法
String类还有一个正则表达式工具,split方法,返回值是一个String数组,它会将字符串从正则表达式匹配的地方切开
for(String temp : "boo:and:foo".split(":")){
System.out.println(temp + " ");
}
//boo and foo
for(String temp : "boo:and:foo".split("o")){
System.out.print(temp + " ");
}
b :and:f
冒号换成\W结果一样,从第二个看出,匹配的是o,它以o为分隔符进行分解
split还有一个重载版本,可以指定分割的次数,放上文档里面的示例
The string "boo:and:foo"
, for example, yields the following results with these parameters:
Split example showing regex, limit, and result Regex Limit Result : 2 { "boo", "and:foo" }
: 5 { "boo", "and", "foo" }
: -2 { "boo", "and", "foo" }
o 5 { "b", "", ":and:f", "", "" }
o -2 { "b", "", ":and:f", "", "" }
o 0 { "b", "", ":and:f" }
一般来说,比起有限的的String类,我们更愿意构造功能强大的正则表达式对象。
你可以通过调用Pattern.compile方法来编译你的正则表达式,它会生成一个Pattern对象,然后把你想要检索的字符串传入Pattern对象的.matcher()方法中,它会生成一个Matcher对象,它有很多功能可以使用。
1. Matcher,public boolean find()
它会查找与模式匹配的输入序列的下一个子序列,若之前的find方法调用成功,且Matcher并未被重置,若继续调用find,则它会从之前匹配的最后一个字符继续匹配。一旦匹配成功,可以通过start()获取匹配子串的开始位置,end()获取结束位置,但是匹配的子串并不包括该索引上的字符,group获取匹配的字符串,相当于substring(start, end)。
例如写一个可以匹配1到10个数字和字母的qq邮箱(随便编的)
查找字符串中所有匹配的子串,输出起止索引
String str = "[email protected]@qq.com";
Pattern p = Pattern.compile("\\w{1,10}@qq\\.com");
Matcher m = p.matcher(str);
while(m.find()){
System.out.println(m.start() + " " + m.end()
+ " " + m.group());
}
//0 17 [email protected]
//20 37 [email protected]
输出匹配的字符索引0-17,不包括17,继续调用find,他会从上一个查找的最后一个索引开始继续往后找。
2. Pattern,public static boolean matches(String regex, CharSequence input)
这个方法和String类的matchers方法很像
括号可以起到很好的区分作用,比如:(abc)+和abc+表达的意思就不同,后者是匹配ab随后匹配1个或多个c,前者是匹配1个或多个abc序列
贪婪型
除非有其他的选项设置,贪婪表达式会为所有可能的符合条件的字符串去匹配。这样会有一个问题,比如我们的模式只能匹配第一个可能的字符组,但是他还是会继续匹配。
勉强型
和上面相反,它总是尽可能的匹配满足模式的所需的最少字符数,懒惰
占有型
当正则表达式匹配字符串时,它会产生相当多的状态,以便在匹配失败的时候可以回溯。而占有型并不会保存这些中间状态,因此它可以防止回溯。常用于防止正则表达式失控,因此可以使正则表达式执行起来更有效。(没有去深究里面的原理)
贪婪型 | 勉强型 | 占有型 | 如何匹配 |
X? | X?? | X?+ | 一个或零个X |
X* | X*? | X*+ | 零个或多个X |
X+ | X+? | X++ | 一个或多个X |
X{n} | X{n}? | X{n}+ | 恰好n次X |
X{n,} | X{n,}? | X{n,}+ | 至少n次X |
X{n,m} | X{n,m}? | X{n,m}+ | 至少n次,不超过X次 |