正则表达式常用字符
- . 表示匹配任意一个字符
- X* 表示字符X出现了0次或者多次
- X+ 表示字符X出现了1次或者多次
- X? 表示字符X出现0次或者1次
- [abc]表示匹配字符a,b,c中的任意一个,[]里面无论有多少内容,都代表匹配的是一个字符
- [^abc]匹配除 a、b 或 c以外任何字符, []里面的^代表取反
- [ a-z && [ def ] ] (&&表示取交集结果 d、e、f)
- [a-z|A-Z](| 表示取并集结果) a 到 z 或 A 到 Z中的一个
- [\\u4e00-\\u9fff]表示匹配任意一个汉字
- \d 表示的是[0-9]中的一个数字
- \s 表示空白字符(比如制表符,换行符.回车符等)
- \w 表示单个字符[0-9A-Z_a-z]中的一个
- \\\\表示\\
- X{n} 表示字符X出现n次
- X{n,} 表示字符X至少出现n次
- X{n,m} 表示字符X最少出现n次,最多出现m次
- ^ 表示行的开头
- $ 表示行的结尾
- 补充 正则表达式的贪婪、勉强、独占三种匹配量词
- 常用功能
正则表达式其实只需要会用一些常用的的字符匹配规则,就能够写出大多数的字符匹配规则,下面就直接介绍一下常用正则表达式的匹配
. 表示匹配任意一个字符
// .表示任意一个字符(a字符是否匹配.)
System.out.println("a".matches("."));//true
X* 表示字符X出现了0次或者多次
// x*表示x出现0次或者多次(,a字符是否匹配a*)
System.out.println("a".matches("a*"));//true
X+ 表示字符X出现了1次或者多次
// x+表示x出现1次或者多次(aaaa是否匹配a+)
System.out.println("aaaa".matches("a+"));//true
X? 表示字符X出现0次或者1次
// x?表示x出现0次或者1次(a是否匹配a?)
System.out.println("a".matches("a?"));//true
[abc]表示匹配字符a,b,c中的任意一个,[]里面无论有多少内容,都代表匹配的是一个字符
System.out.println("a".matches("[abc]")); //true
[^abc]匹配除 a、b 或 c以外任何字符, []里面的^代表取反
System.out.println("a".matches("[^abc]")); //false
[ a-z && [ def ] ] (&&表示取交集结果 d、e、f)
//交集
System.out.println("G".matches("[A-Z&&[RFG]]"));//true
[a-z|A-Z](| 表示取并集结果) a 到 z 或 A 到 Z中的一个
| 代表取并集,在[]内可以省略,也可以这样表示
[a-zA-Z]或者
[[a-z][A-Z]]或者
[a-z[A-Z]]
//并集,一个意思
System.out.println("a".matches("[a-zA-Z]"));//true
System.out.println("B".matches("[a-z|A-Z]"));//true
System.out.println("a".matches("[a-z[A-Z]]"));//true
System.out.println("a".matches("[a-z]|[A-Z]"));//true
[\u4e00-\u9fff]表示匹配任意一个汉字
System.out.println("中".matches("[\\u4e00-\\u9fff]")); //true
System.out.println("中国".matches("[\\u4e00-\\u9fff]")); //false
\d 表示的是[0-9]中的一个数字
System.out.println("1".matches("\\d"));//true
\s 表示空白字符(比如制表符,换行符.回车符等)
System.out.println(" ".matches("\\s"));//true
\w 表示单个字符[0-9A-Z_a-z]中的一个
System.out.println("_".matches("\\w"));//true
\\表示\
这里补充一下 在java中\不代表任何转义字符,如果想要表示反斜杠,在java中需要在反斜杠前面加一个\转义表示一个"\",在正则表达式中含有"\"的时候,需要加一个\再次转义。
//java中书写的时候\\代表一个\,在正则表达式中\\才匹配一个\,
// 在正则表达式中含有"\"的时候,需要加一个\再次转义,为了区分java
//这里正则表达式中含有两个\,所以要转义2次
System.out.println("\\".matches("\\\\"));//true
X{n} 表示字符X出现n次
// 数字出现5次
System.out.println("12345".matches("\\d{5}"));//true
X{n,} 表示字符X至少出现n次
// 数字至少出现5次
System.out.println("123456".matches("\\d{5,}"));//true
X{n,m} 表示字符X最少出现n次,最多出现m次
// 数字至少出现5次,最多出现7次
System.out.println("1234567".matches("\\d{5,7}"));//ture
^ 表示行的开头
// ^表示一行的开头,只用于开头,注意区分[]内的^
System.out.println("hello sir".matches("^h.*"));//true
$ 表示行的结尾
// $表示一行的结尾,只用于结尾
System.out.println("hello sir".matches(".*ir$"));//true
最后补充一下,上面我们一使用String类中matches方法,然而正则表达式还是要使用下面这种方式来匹配比较好,效率更高一些
Pattern p = Pattern.compile("a*b");// 先编译一下正则表达式的字符串,之后产生的一个模式
Matcher m = p.matcher("aaaaab");//这种模式匹配一下字符串之后产生的结果
boolean b = m.matches();//是否匹配
补充 正则表达式的贪婪、勉强、独占三种匹配量词
在上面提到过 ?(重复0次或1次)、*(重复0次或多次)、+(重复1次或多次)
Greedy Quantifiers 贪婪 | Reluctant Quantifiers 勉强 | Possessive Quantifiers 独占 |
---|---|---|
X? | X?? | X?+ |
X* | X*? | X*+ |
X+ | X+? | X++ |
X{n} | X{n}? | X{n}+ |
X{n,} | X{n,}? | X{n,}+ |
X{n,m} | X{n,m}? | X{n,m}+ |
Greedy
匹配最长。在贪婪量词模式下,正则表达式会尽可能长地去匹配符合规则的字符串,且会回溯。
String str = "aaaa5bbb9A";
Pattern p = Pattern.compile(".{3,10}[0-9]");
Matcher m = p.matcher(str);
while (m.find()) {
System.out.println(m.group());
}
//输出: aaaa5bbb9
解释:
- 首先.{3,10} 会匹配到 aaaa5bbb9A,后面没有字符匹配到【0-9】,不满足
- 会回溯,接着.{3,10} 会匹配到aaaa5bbb9,后面的字符A不满足【0-9】
- 再次回溯,.{3,10} 又去匹配aaaa5bbb,后面的9满足【0-9】结束
Reluctant
匹配最短。在勉强量词模式下,正则表达式会匹配尽可能短的字符串。
String str = "aaaa5bbb9A";
Pattern p = Pattern.compile(".{3,10}?[0-9]");
Matcher m = p.matcher(str);
while (m.find()) {
System.out.println(m.group());
}
//输出:
aaaa5
bbb9
解释:
- 首先.{3,10}? 会匹配到 aaa,后面的字符a匹配到【0-9】,不满足
- 接着.{3,10}? 会匹配到 aaaa,后面的字符5满足【0-9】输出
- 继续找.{3,10}? 会匹配bbb,后面字符9满足条件,输出
- 继续找.{3,10}? 发现后面字符串没有匹配,结束
Possessive :
同贪婪一样匹配最长。不过在独占量词模式下,正则表达式尽可能长地去匹配字符串,一旦匹配不成功就会结束匹配而不会回溯。
String str = "aaaa5bbb9A";
Pattern p = Pattern.compile(".{3,10}+[0-9]");
Matcher m = p.matcher(str);
while (m.find()) {
System.out.println(m.group());
}
//没有输出:
解释:
- 首先.{3,10}+ 会匹配到 aaaa5bbb9A,后面的没有字符匹配到【0-9】,不满足,这个时候,也不再回溯了,直接就结束了
常用功能
分组匹配()
比如下面一个字符串,要匹配出连在一起的3个字母和2个数字
String s = "123zz-3456gg-879vv-001c";
正则表达式
字母是一组,数字是一组,用()表示分组概念
Pattern p = Pattern.compile("(\\d{3,5})([a-z]{2})");
匹配操作:
Matcher m = p.matcher(s);
while (m.find()) {
System.out.println(m.start() + "-" + m.end());
System.out.println("m.group(): " + m.group());
System.out.println("第一组: " + m.group(1));
System.out.println("第二组: " + m.group(2));
System.out.println("---------");
}
打印结果:
0-5
m.group(): 123zz
第一组: 123
第二组: zz
---------
6-12
m.group(): 3456gg
第一组: 3456
第二组: gg
---------
13-18
m.group(): 879vv
第一组: 879
第二组: vv
---------
大小写转换
比如下面的字符串
String str = "Java Java Java I love Java you hate java";
正则表达式
Pattern p = Pattern.compile("java", Pattern.CASE_INSENSITIVE);
匹配操作
StringBuffer buf = new StringBuffer();
int i = 0;
while (m.find()) {
i++;
if (i % 2 == 0) {
m.appendReplacement(buf, "java");// 替换成小写
} else {
m.appendReplacement(buf, "JAVA");// 替换成大写
}
}
System.out.println(buf.toString());
打印结果
JAVA java JAVA I love java you hate JAVA