1 预定义字符类
2 数量词
3 范围词
4 正则表达式的应用
4.1 匹配和切割
4.2 替换
4.3 查找
5 单词边界匹配器
正则表达式就是用于操作字符串的一个规则,正则表达式的规则使用了特殊的符号表示。
1 预定义字符类
. 任何字符(与行结束符可能匹配也可能不匹配)
\D 非数字:[^0-9]
\d 数字:[0-9]
\s 空白字符:[ \t\n\x0B\f\r]
\S 非空白字符:[^\s]
\w 单词字符:[a-zA-Z_0-9]
\W 非单词字符:[^\w]
注意:任何预定义字符没有加上数量词之前都只能匹配一个字符。
System.out.println("任意字符:" + ("e".matches("."))); // true
System.out.println("数字字符:" + ("3".matches("\\d"))); // true
System.out.println("数字字符:" + ("a".matches("\\d"))); // false
System.out.println("数字字符:" + ("13".matches("\\d"))); // false
System.out.println("数字字符:" + ("13".matches("\\d\\d"))); // true
System.out.println("非数字字符:" + ("a".matches("\\D"))); // true
System.out.println("空白字符:" + (" ".matches("\\s"))); // true
System.out.println("空白字符:" + ("\r".matches("\\s"))); // true
System.out.println("非空白字符:" + ("a".matches("\\S"))); // true
System.out.println("非空白字符:" + ("\n".matches("\\S"))); // false
System.out.println("单词字符:" + ("_".matches("\\w"))); // true
System.out.println("非单词字符:" + ("@".matches("\\W"))); // true
2 数量词
X? X,一次或一次也没有
X* X,零次或多次
X+ X,一次或多次
X{n} X,恰好 n 次
X{n,} X,至少 n 次
X{n,m} X,至少 n 次,但是不超过 m 次
System.out.println("? 一次或一次也没有:" + ("2".matches("\\d?"))); // true
System.out.println("? 一次或一次也没有:" + ("".matches("\\d?"))); // true
System.out.println("* 零次或多次:" + ("2".matches("\\d*"))); // true
System.out.println("* 零次或多次:" + ("12233442".matches("\\d*"))); // true
System.out.println("* 零次或多次:" + ("".matches("\\d*"))); // true
System.out.println("+ 至少出现一次:" + ("2".matches("\\d+"))); // true
System.out.println("{次数} 恰好出现n次:" + ("12345678901".matches("\\d{11}"))); // true
System.out.println("{次数,} 至少出现n次:" + ("1234".matches("\\d{3,}"))); // true
System.out.println("{次数1,次数2} 指定出现次数的范围:" + ("12345".matches("\\d{3,11}"))); // true
3 范围词
[abc] a、b 或 c(简单类)
[^abc] 任何字符,除了 a、b 或 c(否定)
[a-zA-Z] a 到 z 或 A 到 Z,两头的字母包括在内(范围)
[a-d[m-p]] a 到 d 或 m 到 p:[a-dm-p](并集)
[a-z&&[def]] d、e 或 f(交集)
注意:范围词里不管内容有多长,没有数量词的配合都只能匹配一个字符而已。
System.out.println("abc".matches("[abc]")); // false
System.out.println("abc".matches("[abc]{3}")); // true
System.out.println("@".matches("[^abc]")); // true
System.out.println("字符可以出现在a-z之间:" + "a".matches("[a-z]")); // true
System.out.println("字符可以出现在a-z和A-Z之间:" + "A".matches("[a-z]")); // false
System.out.println("字符可以出现在a-z和A-Z之间:" + "A".matches("[a-zA-Z]")); // true
System.out.println( "$".matches("[a-zA-Z#$]")); // true
4 正则表达式的应用
正则表达式主要是用于操作字符串的规则,正则表达式对字符串的操作主要有以下几个应用:
- 匹配 matches()
- 切割 split()
- 替换 replaceAll(String regex, String replacement)
- 查找
4.1 匹配和切割
public class Demo3 {
public static void main(String[] args) {
matchesPhone("18792522036");
matchesTel("019-5683999");
testSplit1();
testSplit2();
}
/**
* 需求:编写一个正则表达式匹配一个手机号。第一位:只能是1开头;第二位:3,4,5,7,8 ;长度:11位
*/
public static void matchesPhone(String phone) {
String reg = "1[34578]\\d{9}";
System.out.println(phone.matches(reg) ? "合法手机号" : "非法手机号");
}
/**
* 需求:匹配固定电话。 区号-主机号, 区号:首位是0,长度是3~4;主机号:首位不能是0,长度是7~8
*/
public static void matchesTel(String tel) {
System.out.println(tel.matches("0\\d{2,3}-[1-9]\\d{6,7}") ? "合法固话" : "非法固话");
}
/**
* 需求:按照空格切割
*/
public static void testSplit1() {
String str = "明 天 要 放 假";
String[] datas = str.split(" +");
System.out.println("数组的元素:" + Arrays.toString(datas)); // [明, 天, 要, 放, 假]
}
/**
* 需求:根据重叠词进行切割
*/
public static void testSplit2() {
String str = "大家家家明天天玩得得得得得得得得开心";
String[] datas = str.split("(.)\\1+"); // 如果正则的内容需要被复用,那么需要对正则的内容进行分组。分组的目的就是为了提高正则的复用性。
System.out.println("数组的元素:" + Arrays.toString(datas)); // [大, 明, 玩, 开心]
/*
"(.)\\1+" :
():分组。分组的目的是为了让正则的内容被复用起来。组号是从1开始的,不需要我们指定。
((A)(B(C))) :
第1组:((A)(B(C)))
第2组:(A)
第3组:(B(C))
第4组:(C)
\1:引用第1组匹配到的内容。
*/
}
}
4.2 替换
public class Demo4 {
public static void main(String[] args) {
replaceAll1();
replaceAll2();
}
/**
* 替换
*/
public static void replaceAll1() {
String str = "如有需要请联系:18792522036";
String regex = "1[34578]\\d{9}";
str = str.replaceAll(regex,"****");
System.out.println("被替换的内容是:" + str); // 如有需要请联系:****
}
/**
* 把重叠词换成单个单词
*/
public static void replaceAll2() {
String str = "我我我我要要要要做做做做项项目目目"; // 还原结巴的话----->我要做项目
str = str.replaceAll("(.)\\1+", "$1"); // 如果需要replaceAll方法正则的外部引用组的内容,这时要使用"$组号"。
System.out.println(str); // 我要做项目
}
}
4.3 查找
指定为字符串的正则表达式必须首先被编译为此类的实例。然后,可将得到的正则对象匹配任意的字符串用于创建Matcher对象,执行匹配所涉及的所有状态都驻留在匹配器中,所以多个匹配器可以共享同一模式,因此典型的调用顺序是:
Pattern p = Pattern.compile("a*b");
Matcher m = p.matcher("aaaaab");
boolean b = m.matches();
查找需要使用的对象:
- Pattern(正则对象)
- Matcher(匹配器对象)
匹配器要使用到的方法:
- find() 通知匹配器值匹配字符串,查找符合规则的字符串。如果能查到符合规则的字符串,则返回true,否则返回false。
- group() 获取符合规则的字符串。
注意:使用group方法时一定要先调用find方法让匹配器去查找符合规则的字符串,否则报错。
public class Demo5 {
public static void main(String[] args) {
// 找出三个字母组成的单词
String content = "da jia de jia qi jie shu liao hai kai xin ma";
String reg = "\\b[a-zA-Z]{3}\\b"; // \b 是单词边界匹配器
// 先要把字符串的正则编译成Pattern对象
Pattern p = Pattern.compile(reg);
// 使用正则对象匹配字符串,用于产生一个Matcher对象
Matcher m = p.matcher(content);
/*
System.out.println("有符合的字符串吗?" + m.find());
System.out.println("获取结果:" + m.group());
*/
while(m.find()) {
System.out.println(m.group());
}
}
}
5 单词边界匹配器
\b 单词边界匹配器只是代表了单词的开始或者结束部分,不匹配任何的字符。
public class Demo6 {
public static void main(String[] args) {
System.out.println("hello world".matches("hello\\b world")); // true
System.out.println("hello,world".matches("hello\\b,world")); // true
System.out.println("hello.world".matches("hello\\b.world")); // true
}
}