正则表达式,又称规则表达式。(英语:Regular Expression,在代码中常简写为regex、regexp或RE),计算机科学的一个概念。正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本。
就像一个任务,校验QQ号是否合法:
1、必须是5-10位的
2、0不能作为QQ号的开头
3、必须都是数字
我们如果用双重if语句得这样写:
public class RegularDemo1 {
public static void main(String[] args) {
String s = "023w2341232";
System.out.println(checkQQ(s));
}
public static boolean checkQQ(String qq){
boolean flag = false;
//必须是5-10位的
if(qq.length() >=5 && qq.length()<=10){
//保证不是0开头
if(!qq.startsWith("0")){
flag = true;
//必须都是数字
char[] chars = qq.toCharArray();
for (char aChar : chars) {
if(!Character.isDigit(aChar)){
flag = false;
break;
}
}
}
}
return flag;
}
}
但是,如果换成正则表达式,我们只需要两行代码即可
public static boolean checkQQByRegular(String s){
//使用正则表达式可以很容易地完成字符串地查找、匹配替换地工作
//正则表达式
String regex = "[1-9][0-9][4,9]";
return s.matches(regex);
}
学习正则表达式的目的:通过正则表达式处理了字符串复杂的查找/替换/匹配/分割工作
1001,xiaoliu,18,14
json, xml, html
正则表达式是一个独立于java的技术,不依附于java,它可以在java中使用,也可以在python/JS等中去使用
使用步骤:
1、通过大量的字符串你找规律定义规则
2、使用这种规则去匹配新的字符串
3、匹配成功做出相应的操作
正则表达式的语法规则
1、原义字符
字符本身就是一个正则:a b c \t \n \r \f
public class RegularDemo2 {
public static void main(String[] args) {
//原义字符
String regex = "a";
String str = "ab123241dasdasw&;123.";
System.out.println(str.replaceAll(regex,"X"));
}
}
Xb123241dXsdXsw&;123.
2、元字符
元字符的数量太多,所以我们可以将常用的分为一下几个类别:
字符类:
/*
元字符:
字符类
*/
public class RegularDemo3 {
public static void main(String[] args) {
//表示格式:[]
//[]表示将字符进行归类,可以匹配出现在中括号中的任意一个字符
//只要被匹配的字符串中存在a,b,2中任何一个,都会被替换
String regex = "[ab2]";
String s = "ab123241dasdasw&;123.";
System.out.println(s.replaceAll(regex, "_"));
//^出现在中括号中,代表的意思式取反,对不是ab2的字符进行匹配
regex = "[^ab2]";
System.out.println(s.replaceAll(regex, "+"));
}
}
输出结果:
__1_3_41d_sd_sw&;1_3.
ab+2+2+++a++a+++++2++
范围类:
其实是在字符类的基础之上增加了范围
/*
元字符:
范围类 基于字符类的基础之上增加的内容
*/
public class RegularDemo4 {
public static void main(String[] args) {
String regex = "[ab]";
String s = "abcdefghijklmnBV1232QWE41dasdasw&;123.";
System.out.println("匹配之前:\n" + 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]";
System.out.println();
System.out.println(s.replaceAll(regex, "#"));
//想匹配数字咋办
regex = "[0-9]";
System.out.println(s.replaceAll(regex, "_"));
//既想匹配小写又想匹配大写和数字
regex = "[a-zA-Z0-9&;.]";
System.out.println(s.replaceAll(regex, "_"));
}
}
输出结果:
匹配之前:
abcdefghijklmnBV1232QWE41dasdasw&;123.
====================================
__cdefghijklmnBV1232QWE41d_sd_sw&;123.
______________BV1232QWE41_______&;123.
abcdefghijklmn++1232+++41dasdasw&;123.################1232###41#######&;123.
abcdefghijklmnBV____QWE__dasdasw&;___.
______________________________________
预定义类:
我们在上面的范围类的情况下我们在实际开发中可能会遇到一些常见的需求,比如:判断是否是数字、小写字母、大写字母等这些情况,对应的范围类的正则会比较长,所以在正则表达式中会给我们预定一些有特殊含义的表达式,正则表达式把我们常见的整理了一下
\d == [0-9] 数字
\D == [^0-9] 非数字
空白字符:[\t\n\x0B\f\r] == \s
[^ \t\n\x0B\f\r] == \S
\w == [a-zA-Z0-9]
\W == [^a-zA-Z0-9]
. 任何字符(与行结束符可能匹配也可能不匹配)
/*
\d == [0-9] 数字
\D == [^0-9] 非数字
空白字符:[\t\n\x0B\f\r] == \s
[^ \t\n\x0B\f\r] == \S
\w == [a-zA-Z0-9]
\W == [^a-zA-Z0-9]
. 任何字符(与行结束符可能匹配也可能不匹配)
*/
public class RegularDemo5 {
public static void main(String[] args) {
String regex = "[0-9]";
String s = "abcdefghijklmnB V1232Q WE 41dasdasw&;123.";
System.out.println("匹配之前:\n" + s);
System.out.println("====================================");
System.out.println(s.replaceAll(regex, "_"));
regex = "\\d"; //[0-9] 匹配所有的数字
System.out.println(s.replaceAll(regex, "_"));
regex = "\\D"; //匹配所有非数字的字符
System.out.println(s.replaceAll(regex, "_"));
regex = "\\s"; //匹配所有空白字符
System.out.println(s.replaceAll(regex, "!"));
regex = "\\S"; //匹配所有非空白字符
System.out.println(s.replaceAll(regex, "_"));
regex = "\\w"; //匹配所有的大小写字母和数字
System.out.println(s.replaceAll(regex, "_"));
regex = "\\W"; //匹配所有的非大小写字母和数字
System.out.println(s.replaceAll(regex, "_"));
regex = "."; //匹配任何字符
System.out.println(s.replaceAll(regex, "_"));
regex = "\\.";
System.out.println(s.replaceAll(regex, "_"));
}
}
输出结果
匹配之前:
abcdefghijklmnB V1232Q WE 41dasdasw&;123.
====================================
abcdefghijklmnB V____Q WE __dasdasw&;___.
abcdefghijklmnB V____Q WE __dasdasw&;___.
_________________1232_____41_________123_
abcdefghijklmnB!V1232Q!WE!41dasdasw&;123.
_______________ ______ __ _______________
_______________ ______ __ _________&;___.
abcdefghijklmnB_V1232Q_WE_41dasdasw__123_
_________________________________________
abcdefghijklmnB V1232Q WE 41dasdasw&;123_
边界字符
^:以xxx开头
$:以xxx结尾
\b:单词边界
\B:非单词边界
/*
元字符
边界字符
^:以xxx开头
$:以xxx结尾
\b:单词边界
\B:非单词边界
*/
public class RegularDemo6 {
public static void main(String[] args) {
//在没有中括号的时候,^代表的是以什么开头
String regex = "^ac";
String s = "abcdefg";
System.out.println("匹配之前:\n" + s);
System.out.println("====================================");
System.out.println(s.replaceAll(regex, "_"));
regex = "fg$";
System.out.println(s.replaceAll(regex, "_"));
regex = "\\b";
s = "Hello World 888 1 2 & ; 0 a b c d";
System.out.println(s.replaceAll(regex, "_"));
regex = "\\B";
System.out.println(s.replaceAll(regex, "_"));
}
}
输出结果
匹配之前:
abcdefg
====================================
abcdefg
abcde_
_Hello_ _World_ _888_ _1_ _2_ & ; _0_ _a_ _b_ _c_ _d_
H_e_l_l_o W_o_r_l_d 8_8_8 1 2 _&_ _;_ 0 a b c d
量词
?:出现0次或者1次
+:出现1次或者多次
*:出现任意次
{n}:出现正好n次
{n,m}:出现n-m次
{n,}出现至少n次
/*
元字符
量词分类:
?:出现0次或者1次
+:出现1次或者多次
*:出现任意次
{n}:出现正好n次
{n,m}:出现n-m次
{n,}出现至少n次
*/
public class RegularDemo7 {
public static void main(String[] args) {
//匹配以a开头的0次或者1次
// String regex = "^a?";
String regex = "^b?";
String s = "aaaaabcdefaaaaaag";
System.out.println("匹配之前:\n" + s);
System.out.println("====================================");
System.out.println(s.replaceAll(regex, "_"));
regex = "^a+";
System.out.println(s.replaceAll(regex, "_"));
regex = "^b+";
System.out.println(s.replaceAll(regex, "_"));
regex = "^a*";
System.out.println(s.replaceAll(regex, "_"));
regex = "^b*";
System.out.println(s.replaceAll(regex, "_"));
//{n}:出现正好n次
//匹配a连续出现了6次
//aaaaabcdefaaaaaag
regex = "a{6}";
// s = "aaaaabcdefaaaaaag";
System.out.println(s.replaceAll(regex, "_"));
regex = "a{3}";
System.out.println(s.replaceAll(regex, "_"));
//{n,m}:出现n-m次
regex = "^a{3,4}";
System.out.println(s.replaceAll(regex, "_"));
//{n,}出现至少n次
regex = "a{6,}";
System.out.println(s.replaceAll(regex, "_"));
}
}
输出结果
匹配之前:
aaaaabcdefaaaaaag
====================================
_aaaaabcdefaaaaaag
_bcdefaaaaaag
aaaaabcdefaaaaaag
_bcdefaaaaaag
_aaaaabcdefaaaaaag
aaaaabcdef_g
_aabcdef__g
_abcdefaaaaaag
aaaaabcdef_g
分组:
分组的符号为"()"
/*
元字符:
分组
用小括号表示
*/
public class RegularDemo8 {
public static void main(String[] args) {
//表示匹配的是ab加上n个c
String regex = "abc{1,2}";
String s = "abccccABC123123baCBAabcccccABCabcabcabc123";
System.out.println("匹配之前:\n" + s);
System.out.println("====================================");
System.out.println(s.replaceAll(regex, "_"));
//表示匹配abc这个整体出现了1次到2次
regex = "(abc){1,2}";
System.out.println(s.replaceAll(regex, "+"));
regex = "ABC(123|abc){1,}";
System.out.println(s.replaceAll(regex, "+"));
System.out.println(s.matches(regex)); //false
}
}
输出结果:
匹配之前:
abccccABC123123baCBAabcccccABCabcabcabc123
====================================
_ccABC123123baCBA_cccABC___123
+cccABC123123baCBA+ccccABC++123
abcccc+baCBAabccccc+
false
反向引用:
/*
元字符
反向引用
使用$引用对应组号的内容,每一个匹配的内容组号从1开始编号
*/
public class RegularDemo9 {
public static void main(String[] args) {
//2018-04-27 ---> 04/27/2018
String regex = "(\\d{4})-(\\d{2})-(\\d{2})";
String str = "2018-04-27 2021-12-17";
System.out.println(str.replaceAll(regex, "$2/$3/$1"));
//2018-04-27 ---> 04/27/2018
//分组中如果不想要生成分组编号,可以通过?:来实现
regex = "(\\d{4})-(?:\\d{2})-(\\d{2})";
str = "2018-04-27 2021-12-17";
System.out.println(str.replaceAll(regex, "$2/$1"));
}
}
输出结果:
04/27/2018 12/17/2021
27/2018 17/2021