初识正则
什么是正则?正则有什么好处呢?首先我们看下下面的例子
匹配一个qq号要求必须全是数字且长度在8到12位
public class Test {
public static void main(String[] args) {
//qq号要求长度必须是8到12位的纯数字
String str = "1234567811111";
char[] chars = str.toCharArray();
int strLength = chars.length;
boolean isAllNumber = true;
for (char c :chars) {
if (!Character.isDigit(c)){
isAllNumber = false;
}
}
if (isAllNumber){
if (strLength < 8 || strLength > 12){
System.out.printf("qq号长度必须在8到12位");
}else {
System.out.printf("qq号合法");
}
}else {
System.out.printf("qq号必须全是数字");
}
}
}
试想一下个个验证判断这么写,头不得写秃秃了啊,换一种写法。
public class Test {
public static void main(String[] args) {
//qq号要求长度必须是8到12位的纯数字
String str = "123456781";
String res = str.matches("[0-9]{8,12}") ? "合法qq" : "qq号要求长度必须是8到12位的纯数字";
System.out.println(res);
}
}
你会发现还是正则好啊,那么什么是正则呢?正则表达式(regular expression)描述了一种字符串匹配的模式(pattern),可以用来对字符串进行匹配,替换等等操作。
限定符
注意:任何预定义字符没有加上数量词之前都只能匹配一个字符
System.out.println("a".matches(".")); //true
System.out.println("1".matches("\\d")); //true
System.out.println("12".matches("\\d")); //false
System.out.println("%".matches("\\D")); //true
System.out.println("\r".matches("\\s")); //true
System.out.println("^".matches("\\S")); //true
System.out.println("a".matches("\\w")); //true
System.out.println("a".matches("\\W")); //false
限定符
限定符用来指定正则表达式的一个给定组件必须要出现多少次才能满足匹配。
System.out.println( "a".matches(".") );//true
System.out.println( "a".matches("a") );//true
System.out.println("a".matches("a?") );//true
System.out.println( "aaa".matches("a*") );//true
System.out.println( "".matches("a+") );//false
System.out.println( "aaaaa".matches("a{5}") );//true
System.out.println( "aaaaaaaaaaa".matches("a{5,8}") );//false
System.out.println( "aaa".matches("a{5,}") );//false
System.out.println( "aaaaab".matches("a{5,}") );//true
范围
注意:任何范围字符没有加上数量词之前都只能匹配一个字符
System.out.println( "a".matches("[a]") );//true
System.out.println( "aa".matches("[a]+") );//true
System.out.println( "abc".matches("[abc]{3,}") );//true
System.out.println( "abc".matches("[abc]+") );//true
System.out.println( "dshfshfu1".matches("[^abc]+") );//true
System.out.println( "abcdsaA".matches("[a-z]{5,}") );//false
System.out.println( "abcdsaA12".matches("[a-zA-Z]{5,}") );//true
System.out.println( "abcdsaA12".matches("[a-zA-Z0-9]{5,}") );//true
System.out.println( "abdxyz".matches("[a-cx-z]+"));//false
System.out.println( "bcbcbc".matches("[a-zb-c]{5,}"));//true
System.out.println( "tretrt".matches("[a-z^b-c]{5,}"));//true
定位符
定位符使您能够将正则表达式固定到行首或行尾。它们还使您能够创建这样的正则表达式,这些正则表达式出现在一个单词内、在一个单词的开头或者一个单词的结尾。
定位符用来描述字符串或单词的边界,^ 和 $ 分别指字符串的开始与结束,\b 描述单词的前或后边界,\B 表示非单词边界。
分组
既然知道了正则中基本使用,我们看下他经常用来干嘛?等等使用前我们认识下分组。
注意
- 正则中的分组():目的是为了让正则的内容被复用,组号从1开始
- 如果需要在replaceAll方法正则的外部引用组的内容,那么要使用"$组号"
使用
匹配
需求1:编写一个正则表达式匹配手机号 第一位:1;第二位:3、5、4、7、8;长度:11位
public class Test {
public static void main(String[] args) {
//需求1:编写一个正则表达式匹配手机号 第一位:1;第二位:2、 3、5、4、7、8;长度:11位
String str = "15339076821";
String res = str.matches("1[35478]\\d{9}") ? "合法手机号" : "手机号格式错误";
System.out.println(res);
}
}
需求2:编写一个正则表达式匹配固定电话 区号-主机号 区号:首位是0 长度3-4;主机号:首位不是0、长度7-8位
public class Test {
public static void main(String[] args) {
//需求2:编写一个正则表达式匹配固定电话 区号-主机号 区号:首位是0 长度3-4;主机号:首位不是0、长度7-8位
String str = "0553-5621789";
String res = str.matches("0[1-9]{2,3}-[1-9]{7,8}") ? "合法固定电话" : "固定电话格式错误";
System.out.println(res);
}
}
分割
需求1:需求1:将 明 天 放 假 =》 明天放假
public class Test {
public static void main(String[] args) {
//需求1:将 明 天 放 假 => 明天放假;
String str = "明 天 放 假";
String[] res = str.split(" +");
String s = StringUtils.join(res);
System.out.println(s);
}
}
需求2:出去重叠词 好好学习天天向上 => 学习向上
public class Test {
public static void main(String[] args) {
//需求2:出去重叠词 好好学习天天向上 => 学习向上
String str = "好好学习天天向上";
String[] res = str.split("(.)\\1+");
String s = StringUtils.join(res);
System.out.println(s);
}
}
替换
需求1:替换 “如有需求请联系13345678912”中的手机号为*********
public class Test {
public static void main(String[] args) {
//需求1:替换 如有需求请联系13345678912 中的手机号为*********
String str = "如有需求请联系13345678912";
String s = str.replaceAll("1[35478]\\d{9}","*********");
System.out.println(s);
}
需求2:还原结巴的话我我我要要要要学习做做做项目
public class Test {
public static void main(String[] args) {
//需求2:还原结巴的话我我我要要要要学习做做做项目
String str = "我我我要要要要学习做做做项目";
String s = str.replaceAll("(.)\\1+","$1");
System.out.println(s);
}
}
Pattern类(正则对象)、Matcher(匹配器对象)
匹配一个单词边界,。
用法与流程
Pattern p = Pattern.compile(“正则”);
Matcher m = p.matcher(“aaaaab”);
m.find()或m.group()
- 先将正则表达式编译成正则对象,使用的是Pattern类一个静态的方法;
- 让正则对象和要操作的字符串相关联,通过matcher方法完成,并返回匹配器对象;
- 通过匹配器对象的方法将正则模式作用到字符串上对字符串进行针对性的功能操作。
- find 查找符合规则的字符串,找到返回true,否则false
- group 返回符合规则的字符串
注意:必须先find再group否则报错。
需求1:获取由3个字母组成的单词
public class Test {
public static void main(String[] args) {
String str = "da jia zhu yi le,wo men fang jia la";
String reg = "[a-zA-Z]{3}";
Pattern p = Pattern.compile(reg);
Matcher m = p.matcher(str);
while(m.find())
{
//获取方式一
//System.out.println("sub:"+str.substring(m.start(),m.end()));
//获取方式二
System.out.println("group:"+m.group());
}
}
}
结果
group:jia
group:zhu
group:men
group:fan
group:jia
我们发现 fang中的fan也被匹配出来了,那如何解决这个问题呢?
\b
单词边界匹配址,只代码单词的开始或结束,本身不匹配任何实际字符看代码。
public class Test {
public static void main(String[] args) {
System.out.println("hello word".matches("hello\\bword"));//false
System.out.println("hello word".matches("hello\\b word"));//true
System.out.println("hello word".matches("\\bhello\\b word"));//true
System.out.println("hello,word".matches("\\bhello\\bword"));//false
System.out.println("hello,word".matches("\\bhello\\b,word"));//true
}
}
public class Test {
public static void main(String[] args) {
String str = "da jia zhu yi le,wo men fang jia la";
String reg = "\\b[a-zA-Z]{3}\\b";
Pattern p = Pattern.compile(reg);
Matcher m = p.matcher(str);
while(m.find())
{
//获取方式一
//System.out.println("sub:"+str.substring(m.start(),m.end()));
//获取方式二
System.out.println("group:"+m.group());
}
}
}
结果:
group:jia
group:zhu
group:men
group:jia