正则表达式是独立于java的技术,不依附于java,但是它可以在java中使用,也可以在python/js等中使用
通过正则表达式处理字符串复杂的查找/替换/匹配/分割工作
使用单个字符串来描述或者匹配一系列符合某种语法规则的字符串
(1)通过大量的字符串寻找规律,得出定义规则
(2)使用这种规则去匹配新的字符串
(3)匹配成功做出相应的操作
1、原义字符:字符本身就是一个正则
String str = "ab1&;3.";
//public String replaceAll(String regex,String replacement)
// 用给定的字符串替换与给定的regex匹配的此字符串的每个子字符串。
String regex = "\\.";
System.out.println(str.replaceAll(regex,"_"));//ab1&;3_ 替换了.
regex = "b";
System.out.println(str.replaceAll(regex,"_"));//a_1&;3. 替换了b
2、元字符
(1)字符类 [ ]
public class RegularDemo3 {
public static void main(String[] args) {
String s = "ab123342asdasqwe&;123.";
//表示格式:[]
//[]表示的是将字符进行归类,可以匹配出现在中括号中的任意一个字符
//只要被匹配的字符串中存在a,b,2中任何一个,都会被匹配到
String regex = "[ab2]";
System.out.println(s.replaceAll(regex,"_"));
//需求:除了ab2以外,都要被匹配替换
//^出现中括号代表的意思是取反,对不是ab2的字符进行匹配
regex = "[^ab2]";
System.out.println(s.replaceAll(regex,"_"));
}
}
//结果 __1_334__sd_sqwe&;1_3.
ab_2___2a__a_______2__
(2)范围类
其实就是在字符类的基础上增加了一个范围
public class RegularDemo4 {
public static void main(String[] args) {
String regex = "[ab]";
String s = "abcdefghijklmnABCDTW1234DWFadqwr&;123=.";
System.out.println("匹配之前:" + s);
System.out.println("=========================================");
System.out.println(s.replaceAll(regex, "_"));
//需求:匹配字符串中所有小写的字母
//[a-z]表示的是匹配a到z中的任意一个小写字母
regex = "[a-z]";
System.out.println(s.replaceAll(regex, "_"));
//[A-Z]表示的是匹配A到Z中的任意一个大写字母
regex = "[A-Z]";
System.out.println(s.replaceAll(regex, "_"));
//又想匹配大写,又想匹配小写呢?
// regex = "[a-zA-Z]"; regex = "[A-z]";
System.out.println(s.replaceAll(regex, "_"));
//现在想匹配数字怎么办?
regex = "[0-9]";
System.out.println(s.replaceAll(regex, "_"));
//又想匹配数字又想匹配大小写字母
regex = "[0-z&.]";
System.out.println(s.replaceAll(regex, "_"));
}
}
结果
匹配之前:abcdefghijklmnABCDTW1234DWFadqwr&;123=.
=========================================
__cdefghijklmnABCDTW1234DWF_dqwr&;123=.
______________ABCDTW1234DWF_____&;123=.
abcdefghijklmn______1234___adqwr&;123=.
____________________1234________&;123=.
abcdefghijklmnABCDTW____DWFadqwr&;___=.
_______________________________________
(3)预定义类
根据上面的范围类,对应可以互换
\d == [0-9]数字
\D == [^0-9]非数字
\s == [\r\n\f\r]空白字符
\S == [^\r\n\f\r]空白字符
\w == [a-zA-Z0-9]
\W == [^a-zA-Z0-9]
以上用的是时候加双\\,例:\\d
. == 代表任意字符
\\.表示.字符
(4)边界类字符
^: 不在中括号中出现,表示的是以xxx开头
$: 以xxx结尾
下面用的时候也是双\\
\b: 单词边界,此单词非彼单词,单个的字母也是单词
\B: 非单词边界
String regex = "^abc";
String s = "abcdefg";
System.out.println("匹配之前:" + s);
System.out.println("=========================================");
System.out.println(s.replaceAll(regex, "_"));
regex = "fg$";
System.out.println(s.replaceAll(regex, "_"));
regex = "\\b";
s = "hello worpd 888 1 2 & ; 0 a b c d";
System.out.println("匹配之前:" + s);
System.out.println("===========================================");
System.out.println(s.replaceAll(regex, "_"));
regex = "\\B";
System.out.println(s.replaceAll(regex, "_"));
结果:
匹配之前:abcdefg
=========================================
_defg
abcde_
匹配之前:hello worpd 888 1 2 & ; 0 a b c d
===========================================
_hello_ _worpd_ _888_ _1_ _2_ & ; _0_ _a_ _b_ _c_ _d_
h_e_l_l_o w_o_r_p_d 8_8_8 1 2 _&_ _;_ 0 a b c d
(5)量词
? : 出现了0次或者1次
+:出现了1次或者多次
*:出现了任意次
{n}:出现了正好n次
{n,m}:出现了n-m次
{n, };表示出现了至少n次
//匹配以a开头的0次或者1次
String regex = "^a?";
String s = "baaabcdefaaaaaag";
System.out.println("匹配之前:" + s);
System.out.println("=======================================");
System.out.println(s.replaceAll(regex, "_"));
regex = "^a+";
System.out.println(s.replaceAll(regex, "_"));
regex = "^a*";
System.out.println(s.replaceAll(regex, "_"));
//{n}:出现了正好n次
//需求:匹配一个字符串a字符连续出现了6
regex = "a{6}"; // aaaaaa
System.out.println(s.replaceAll(regex, "*"));
//{n,m}:出现了n-m次
regex = "a{3,4}"; // 匹配的是a连续出现的次数在3-4之间
System.out.println(s.replaceAll(regex, "*"));
//{n, };表示出现了至少n次
regex = "a{6,}";
System.out.println(s.replaceAll(regex, "*"));
//验证qq
regex = "[1-9][0-9]{4,9}";
s = "1165872335";
System.out.println(s.replaceAll(regex, "匹配成功"));
结果
匹配之前:baaabcdefaaaaaag
=======================================
_baaabcdefaaaaaag
baaabcdefaaaaaag
_baaabcdefaaaaaag
baaabcdef*g
b*bcdef*aag
baaabcdef*g
匹配成功
(6)分组 ( )
String s = "abccccabc123abcabc123A";
//加上小括号表示分组
//表示abc整体出现了1-2次
reagex = "(abc){1,2}";
System.out.println(s.replaceAll(reagex, "_"));
结果:_cc_123__123A
(7)反向引用(用来取值的)
$: 取值,取对应分组号中的值,每一个分组的编号从1开始
/*
需求:2022-01-23 ---> 01/23/2022 使用正则中的反向引用完成
*/
public class RegularDemo9 {
public static void main(String[] args) {
//2022-01-23
String regex = "(\\d{4})-(\\d{2})-(\\d{2})";
String s = "2022-01-23 2022-02-24";
System.out.println(s.replaceAll(regex,"$2/$3/$1"));
//分组中如果我不想让它生成编号 ?:
regex = "(\\d{4})-(?:\\d{2})-(\\d{2})";
// System.out.println(s.replaceAll(regex,"$2/$3/$1"));
System.out.println(s.replaceAll(regex,"$2/$1"));
}
}
结果;
01/23/2022 02/24/2022
23/2022 24/2022
在java中是如何让使用正则表达式来实现相关操作的?
1、字符串的查找操作:Pattern和Matcher
2、字符串的匹配操作:可以使用该字符串的matches方法
3、字符串的替换操作:字符串String类中有replaceAll()方法和replaceFirst()方法
4、字符串的分割工作:字符串String类中有split()方法
import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegularDemo10 {
public static void main(String[] args) {
String regex = "\\w{3,}";
String s = "abcd123";
System.out.println(s.matches(regex));//查看是否存在
regex = "[a-z]{2,}";
s = "abc defg hello111";
System.out.println(s.replaceAll(regex, "_"));//替换所有的
System.out.println(s.replaceFirst(regex, "_"));//只替换第一个
s = "abc sbdf 123ab sa123bddss &";
String[] s1 = s.split(" ");//以空格进行分割
//工具类遍历数组
System.out.println(Arrays.toString(s1));//标准输出
s = "abc sbdf 123ab sa123bddss &";
String[] s2 = s.split("a");//以a进行分割
//工具类遍历数组
System.out.println(Arrays.toString(s2));
//Pattern和Matcher
regex = "\\w{3,7}";
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher("abcd123");
System.out.println(m.matches());
}
}
输出结果:
true
_ _ _111
_ defg hello111
[abc, sbdf, 123ab, sa123bddss, &]
[, bc sbdf 123, b s, 123bddss &]
true
Pattern和Matcher的用法
Pattern p = Pattern.compile("a*b");
Matcher m = p.matcher("aaaaab");
System.out.println(m.matches());
pattern中是正则表达式,matcher是将要进行操作的字符串和正则表达式放在一起,运用Matcher中的方法进行操作。
举例:
星期:Monday(星期一)....Sunday(星期日)
性别:Man(男),Woman(女)
季节:Spring(春天)...winter(冬天)
定义一个枚举类:根据JDK的版本不同,实现的方式不同
JDK1.5之前:自定义一个枚举类
自定义一个枚举类:
package com.shujia.wyh.day16;
/*
自定以一个季节枚举类
*/
public class EnumDemo1 {
public static void main(String[] args) {
Season spring = Season.SPRING;
System.out.println(spring);
System.out.println(spring.getSEASON_NAME());
System.out.println(spring.getSEASON_DESC());
}
}
class Season{
//2、创建Seanson的成员变量,必须把它定义为常量
private final String SEASON_NAME;
private final String SEASON_DESC;
//1、需要将构造方法私有化,保证类的对象的个数是有限个的
private Season(String SEASON_NAME,String SEASON_DESC){
this.SEASON_NAME = SEASON_NAME;
this.SEASON_DESC = SEASON_DESC;
}
//3、提供公共的静态的成员变量给外界获取枚举类的对象
public static final Season SPRING = new Season("春天","春暖花开");
public static final Season SUMMER = new Season("夏天","烈日炎炎");
public static final Season AUTUMN = new Season("秋天","秋高气爽");
public static final Season WINTER = new Season("冬天","白雪皑皑");
//4、只提供公共的get方法
public String getSEASON_NAME() {
return SEASON_NAME;
}
public String getSEASON_DESC() {
return SEASON_DESC;
}
//5、重写toString()方法
@Override
public String toString() {
return "Season{" +
"SEASON_NAME='" + SEASON_NAME + '\'' +
", SEASON_DESC='" + SEASON_DESC + '\'' +
'}';
}
}
输出结果:
Season{SEASON_NAME='春天', SEASON_DESC='春暖花开'}
春天
春暖花开
JDK1.5之后:通过关键字enum定义枚举类
public class EnumDemo2 {
public static void main(String[] args) {
Season2 spring = Season2.SPRING;
System.out.println(spring);
System.out.println(Season2.class.getSuperclass());
}
}
/**
* 自定义一个季节枚举类
*/
enum Season2{
//3、枚举有的有限个对象,对象之间通过逗号连接,最后一个分号结尾
//枚举相关的放在头部
SPRING("春天", "万物复苏"),
SUMMER("夏天", "万物复苏2"),
AUTUMN("秋天", "万物复苏3"),
WINTER("冬天", "万物复苏4");
//2、创建Season2的属性,常量处理
private final String SEASON_NAME;
private final String SEASON_DESC;
//1、要保证类的对象的个数是有限的
//那么我们必须要私有构造方法
private Season2(String SEASON_NAME,String SEASON_DESC){
this.SEASON_NAME = SEASON_NAME;
this.SEASON_DESC = SEASON_DESC;
}
//4、提供SEASON_NAME和SEASON_DESC的get方法
public String getSEASON_NAME() {
return SEASON_NAME;
}
public String getSEASON_DESC() {
return SEASON_DESC;
}
//5、重写toString()
// @Override
// public String toString() {
// return "Season{" +
// "SEASON_NAME='" + SEASON_NAME + '\'' +
// ", SEASON_DESC='" + SEASON_DESC + '\'' +
// '}';
// }
}
(1)直接在枚举类实现接口中的抽象方法
(2)在每个枚举对象中实现