今天带大家了解一下Java当中的正则,依旧采用我自己 “”学习一个知识点的四部曲!“”
学习一个知识点的四部曲!
1.什么是它(正则)?
2.用它(正则)有什么好处? (这里得抛砖引玉,先讲没有它会出现什么问题,有了它解决了什么问题)
突然想到了,先抑后扬,也叫欲扬先抑这种修辞手法
3.它主要包含哪些知识点(列出大纲)?
4.怎么使用它?
一:什么是它(正则)?
计算机科学的一个概念。正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本
Regular Expression,在代码中常简写为regex、regexp或RE
二:用它(正则)有什么好处?
2.1没他时
例子:可能你在前端验证个邮箱,都得写满大屏幕的 if 代码,有了正则之后,轻松搞定
2.2有他时
上述的问题,根本就不是问题,当然正则不止止这么一点功能,上面只是举一个例子
正则的作用主要是用来:查找,替换,匹配
三:它主要包含哪些知识点(列出大纲)?
3.1 元字符,量词,方括号
3.2 介绍下Java中的正则对应的类 (Pattern 和 Matcher) 及其常用方法
3.3 String类中涉及正则的几个方法
四:怎么使用它?
关于怎么使用它,其实就是把上面的含义都搞懂,把下面的练习都敲一遍就基本上入门了
量词:
3.1.1元字符案列
package 字符串.原字符;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 正则的作用: 查找,替换,匹配
* 仔细一察觉,其实工作中经常用: 查找(Ctrl+F),替换(replace),搜索某些文件会用*匹配
*
* 演示一下: 元字符 和 量词的用法
* @author wzj
*
*/
public class Demo {
public static void main(String[] args) {
/**
* 元字符:只能匹配单个字符
* . :表示任意的单个字符
* /d:digits(数字),匹配0~9中任意一个字符
* /s:space(空格), 匹配所有空白字符:如空格,制表符(\t),换行符,回车符等
* /w:word(单词) a~zA~Z,0~9,_
*
* /D,/S,/W 大写的都是表示非
* 例子: /D: 匹配非数字
*
*
* 量词: 问嘉兴, 是表示前面这个字符的次数,例子: a?,说明可以匹配 "空字符串" 和 "一个a的"的字符串
* ? : 0次或1次
* + : 1次或多次
* * : 0次或多次
* 这里可以画个三角形!
*/
//Pattern对象是正则表达式编译完后在内存中的表现形式!!
Pattern p = Pattern.compile("\\d");
Matcher m = p.matcher("12");//只能匹配单个数字
System.out.println(m.matches());//fasle
//如果我想表示1个或多个数字呢?就得用量词: ? + * (问嘉兴)
boolean b2 = Pattern.compile("\\d+").matcher("2232323323").matches();
System.out.println(b2);//true,这样的话就能匹配多个数字,这个正则除了出现数字,不能出现其他的
//如果只使用一次正则,就用这种方式
boolean b3 = Pattern.matches(".", "我的");
System.out.println(b3);//false, 只能匹配任意单个字符
boolean b4 = Pattern.matches(".*", "有点帅");
System.out.println(b4);//true
boolean b5 = Pattern.matches("ab?", "");
System.out.println(b5);//false, 注意:量词只是匹配前一个字符的个数,这里也就是b的次数
//如果想将ab表示成一个整体,得用()括起来
boolean b6 = Pattern.matches("(ab)?", "");
System.out.println(b6);//true,因为?代表: 0次或1次
boolean b7 = Pattern.matches("\\w", "Z");
System.out.println(b7); //true,因为\w匹配: a~z,A~Z(字母),0~9(数字),_(下划线)
boolean b8 = Pattern.matches("\\D", "Z");
System.out.println(b8);//true,因为\\D,匹配非数字
System.out.println(Pattern.matches(".", " ")); //. 可以匹配空格
}
}
3.1.2 量词案列
package 字符串.原字符;
import java.util.regex.Pattern;
/**
* 量词的用法:
* ?: 表示前面字符的0次或1次
* +: 表示前面字符的1次或多次
* *: 表示前面字符的0次或多次
* 帅{x},匹配包含x个“帅”的字符串
* 帅{x,y}: 匹配x或者y个“帅”的字符串
* 帅{x,}: 匹配至少x个“帅”的字符串
* 帅$: 匹配任何结尾为“帅”的字符串,只能匹配单个字符!!
* ^帅: 匹配任何开头为“帅”的字符串,只能匹配单个字符!!
*
* 注意事项: 注意除了使用量词,不然只能匹配单个字符!!!
* 可能没有全部列全,但常见的就这些,用到频率多的,可以以后自己再补充!!
* @author wzj
*
*/
public class Demo3 {
public static void main(String[] args) {
boolean b = Pattern.matches("我是大帅{1}比", "我是大帅比");
System.out.println(b);//true
//固定每天帅一次
boolean b2 = Pattern.matches("我是大帅{1}比", "我是大帅帅比");
System.out.println(b2);//false
//帅一次或者两次
boolean b3 = Pattern.matches("我是大帅{1,2}比", "我是大帅帅比");
System.out.println(b3);//true
//需求:至少帅两次
boolean b4 = Pattern.matches("我是大帅{2,}比", "我是大帅帅比");
System.out.println(b4);//true
boolean b5 = Pattern.matches("帅$", "有点帅");
System.out.println(b5);//false: 注意除了使用量词,不然只能匹配单个字符!!!
// boolean b6 = Pattern.matches("*帅$", "有点帅");
// System.out.println(b6); //这个会报错,我们说了量词,是匹配前一个字符的次数,而这个*前面没有字符!!所以报错
boolean b7 = Pattern.matches("[^x00-xff]*帅$", "有点帅");
System.out.println(b7);//true, [^x00-xff]:是匹配中文的正则
// boolean b8 = Pattern.matches("[^x00-xff]", "d"); //false
boolean b8 = Pattern.matches("[^x00-xff]", "我的");
System.out.println(b8);//false, 也是只能表示单个字符!!!
boolean b9 = Pattern.matches(".*帅$", "有点帅");
System.out.println(b9);//true, .代表任意单个字符!!
}
}
3.1.3 方括号
package 字符串.原字符;
import java.util.regex.Pattern;
/**
* 方括号:
* [abc]: 表示枚举,表示a,b,c任意一个字符
* [^abc]: 表示非a,b,c的任意字符
* [0-9]: 表示0~9之间的任意字符
* [a-z]: 表示a~z之间的任意字符
* [A-Z]: 同理
* [red|blue|green]:查找任意指定的选项,和[abc]类似!
*
* @author wzj
*
*/
public class Demo2 {
public static void main(String[] args) {
boolean b = Pattern.matches("[abc]", "a");
System.out.println(b);//true, 表示只要满足a,b,c中任意一个字符就行!
boolean b2 = Pattern.matches("[^abc]", "de");
System.out.println(b2);//false, 只能满足非a,b,c的 “单个” 字符, 要想满足多个得用量词!!
boolean b3 = Pattern.matches("[^abc]+", "de");
System.out.println(b3);//true
boolean b4 = Pattern.matches("[^abc]+", "ad");
System.out.println(b4);//false, 这个+量词,把前面[]中看成了一个整体,要么存在单个非a,b,c 要么多个!!
boolean b5 = Pattern.matches("[0-9]", "55");
System.out.println(b5);//false, 注意还是只能匹配单个字符!!!
boolean b6 = Pattern.matches("[a-z]", "ab");
System.out.println(b6);//false,还是只能匹配单个字符,匹配多个得用量词: ? + *
boolean b7 = Pattern.matches("[苹果|橘子|香蕉]", "橘子");
System.out.println(b7);//fasle, 注意:只能匹配单个字符!!
boolean b8 = Pattern.matches("(苹果|橘子|香蕉)", "橘子");
System.out.println(b8);//true, 使用()才是可以的
boolean b9 = Pattern.matches("[苹果|橘子|香蕉]", "橘");
System.out.println(b9);//true
}
}
3.2 介绍下Java中的正则对应的类 (Pattern 和 Matcher) 及其常用方法
3.2.1
package 字符串.原字符;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/*
* 介绍一下Java中的正则表达式!!
* Pattern:模式
* Matches:匹配器
*/
public class Demo4 {
public static void main(String[] args) {
//Java中的正则,提供了Pattern和
//第一种写法: Pattern对象是正则表达式编译完后,在内存中的表现形式!!
Pattern p = Pattern.compile("^H\\d{2,}\\w{3}P$");
Matcher m = p.matcher("H123abcP");
System.out.println(m.matches());//true
Matcher m2 = m.reset("H123abcPW");//rest方法:可以将现有的Matcher对象应用于一个新的字符序列!
System.out.println(m2.matches());//false
//第二种写法:可以使用链式编程的写法
boolean b = Pattern.compile("^H\\d{2,}\\w{3}P$").matcher("H123abcP").matches();
System.out.println(b);//true
//第三种写法: 如果某个正则表达式只用一次,那么直接使用Pattern类中matches()静态方法
boolean b2 = Pattern.matches("^H\\d{2,}\\w{3}P$", "H123abcP");
System.out.println(b2);//true
//第四种写法
System.out.println("hello".matches("\\w+"));//true
}
}
3.2.2
package 字符串.原字符;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 介绍Matcher类中的一些常用方法
* @author wzj
*
*/
public class Demo6 {
public static void main(String[] args) {
/**
* 介绍一下matches方法和find方法
* matches:是全部匹配,字符串要完全对应正则的规则
* find:是部分匹配 ,字符串中的子串满足就行,全部满足还不行!!
*/
Pattern p1 = Pattern.compile("\\d");
Matcher m1 = p1.matcher("1");
System.out.println(m1.matches());//true :全部匹配: 跟equals方法作用类似
System.out.println(m1.find());//false :find方法是部分匹配,全部匹配还不行!!
Pattern p2 = Pattern.compile("\\d");
Matcher m2 = p2.matcher("12");
System.out.println(m2.matches());//false: 没有完全匹配,因为\\d只表示任意单个数字,而字符串是两个
System.out.println(m2.find());//true: 部分匹配!
Matcher matcher = Pattern.compile("\\w").matcher("Java is very easy!");
while(matcher.find()) {//find():判断目标字符串中是否包含与Pattern匹配的子串
System.out.print(matcher.group());//返回上一次和Pattern匹配的子串: 可以看出一般和find()一起使用,直接使用会报错
}
//start和end方法主要用于确定子串在目标字符串中的位置
//创建一个Pattern对象,并用他建立一个Matcher对象
String destStr = "Java is Very easy!";
System.out.println("目标字符串:"+ destStr);
Matcher matcher2 = Pattern.compile("\\w+").matcher(destStr.trim()); //遇到空格就会结束
while(matcher2.find())
{
System.out.println(matcher2.group()+"\t子字符串的起始位置:"+matcher2.start()+"\t子串的结束位置:"+matcher2.end());
}
}
}
3.3 String类中涉及正则的几个方法
package 字符串.原字符;
import java.util.Arrays;
/***
* String类中,涉及到正则的几个方法
*
* boolean matches(String regex); 判断该字符串是否匹配正则
* String replaceAll(String regex,String replacement);将字符串中匹配正则的子串替换后返回!!
* String replaceFirst(String regex,String replacement);将字符串中匹配正则的“首个子串”替换后返回!!
* String[] split(String regex); 根据正则拆分字符串,得到一个字符串数组!
* @author wzj
*
*/
public class Demo5 {
public static void main(String[] args) {
//1.matches用法!!
// testMatches();
//2.replaceAll用法!!
// testReplaceAll();用法!!
//3.replaceFirst
// testReplaceFirst();
//4.split();用法!!
testSplit();
}
private static void testSplit() {
String str = "hello , java";
String[] split = str.split(",");
System.out.println(Arrays.toString(split));
}
private static void testReplaceFirst() {
String str = "hello , java";
System.out.println(str.replaceFirst("\\w*", "♠"));//♠ , java:*遇到空格就停了
}
private static void testReplaceAll() {
String str = "我12爱的12我的12国家";
String newStr = str.replaceAll("\\d", "A");//将数字替换成A
System.out.println(newStr);
}
private static void testMatches() {
String str = "Hello World";
System.out.println(str.matches("^H"));//false,除了使用量词,只能匹配单个字符!!
System.out.println(str.matches("^H\\w*"));//false, \w遇到空格就没了
System.out.println(str.matches("^H\\w*\\s\\w*"));//true
}
}
练习:
package 字符串.练习;
import java.util.regex.Pattern;
//https://blog.csdn.net/qian_youyou/article/details/79121916
public class Demo1 {
public static void main(String[] args) {
//1.匹配整数的正则: 负整数,正整数,0
boolean b = Pattern.matches("\\d+", "0");
System.out.println(b);//这里的正则是可以将0 和 正整数搞定
boolean b2 = Pattern.matches("-?\\d+", "-12");
System.out.println(b2);// 需要让-可有可无, 所以用?搞定
//2.匹配非负整数的正则: 非负整数: 0 和 正整数!
boolean b3 = Pattern.matches("\\d+", "-1");
System.out.println(b3);
//3.匹配非正整数: 0 和 负整数
boolean b4 = Pattern.matches("[-\\d+|0]", "-1545");
System.out.println(b4);//fasle:[]里面只能匹配单个字符,所以用量词(?+*)作用不大!!
boolean b5 = Pattern.matches("[-\\d|0]", "-");
System.out.println(b5);//true: []:只能匹配单个字符: -, 多一个\\d就不匹配!!!
boolean b5_2 = Pattern.matches("[-\\d|0]", "-1");
System.out.println(b5_2);//fasle: 因为[]只能匹配单个字,- 和 1 是两个字符,所以不匹配!!!
boolean b6 = Pattern.matches("[我的|你]", "我的");
System.out.println(b6);//false: []里面只能匹配单个字符,所以用量词(?+*)作用不大!!
boolean b7 = Pattern.matches("(我的|你)", "我的");
System.out.println(b7);//true:
boolean b8 = Pattern.matches("(0|-\\d+)", "-65454");
System.out.println(b8);//ture: 表示0 或者 负整数
}
}
package 字符串.练习;
import java.util.regex.Pattern;
public class Demo2 {
public static void main(String[] args) {
//1.长度为8-10的用户密码(以字母开头、数字、下划线)
boolean b = Pattern.matches("^[A-z]\\w{7,10}", "Z1272sdsd");
System.out.println(b);//true: [A-z]表示[a-zA-Z]中任意单个字符!!
//2.验证输入只能是汉字
boolean b2 = Pattern.matches("^[\\u4e00-\\u9fa5]{1,}$", "我");
System.out.println(b2);//true: 至少匹配一个汉字{1,}等价于+,没看u4e00是什么鬼
//3.电子邮箱验证 itcast_wzj,[email protected], [email protected],可以满足
boolean b3 = Pattern.matches("^\\w{7,10}@\\w{2,3}.(com|cn)", "[email protected]");
System.out.println(b3);
// ^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
boolean b4 = Pattern.matches("^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$", "[email protected]");
System.out.println(b4);
System.out.println(Pattern.matches("([-+.]\\w+)*", ""));//true: 这个整可以是0 或者 是多个
System.out.println(Pattern.matches("([-+.]\\w+)*", "-dd-dd"));//true
System.out.println(Pattern.matches("([-+.]\\w+)*", "-dd-d"));//true??????????? //TODO
/**
* 这个正则挺好玩的
* 1.先看圆括号里面的: [-+.]\\w+ 表示从-+.任意单个字符, 而\\w+ 表示一个或多个
* 例子: 满足的字符串: -d 或 -ddd
* 2.然后看()*,圆括号把他们当成了一个整体, *表示0或多个
* 表示多个的例子: -d-d-d 或 -ddd-ddd-ddd
* 表示多个的例子: 空字符串即可满足!!
*/
}
}
最后想说一下,学完之后找几个题目练练手,不然不知道它的强大之处,正则其实是挺重要的,不要以为我验证一个邮箱,去网上一搜一大把,但有时候正则可以把你处理一些特殊的字符串需求,可以省了很多的代码,我在公司就见过别人不用正则写的一大把逻辑且繁琐才解决问题,用了正则又方便,又简洁,而且正则在java中会用到,JS中也会用到,linux下也会用到,就平时在eclipse中查找的时候,也会用到,把它学会何乐而不为呢?
疑问:System.out.println(Pattern.matches("([-+.]\\w+)*", "-dd-d"));//true 这个为什么是true啊??
看到时候回过头来,能不能解决!!
System.out.println(Pattern.matches("(-\\w+)*", "-dd-d"));
/**
* 我知道为什么是true了,因为多了个+的原因
是把括号中看成一个整体
* 第一次. -\\w+: 可能是-dd
* 第二次. -\\w+: 可能是-d
* 然后*代表 0次 或 多次
*
* 之前的理解是先固定死()中的内容,然后看* :就是说假如()里是 -a, 然后我再*,所以我就认为,要么-a不出现,要么就是-a-a这样的规律 出现!!
* 现在的理解就是:()中表达式能够出现几次!!!
*/
System.out.println(Pattern.matches("(-\\w)*", "-dd-d"));//fasle