h
hellotqq
V1
2023/02/03阅读:19主题:默认主题
一文搞定正则表达式
本篇文章来学习下正则表达式,文章主要通过代码和代码中的注解进行展开,本文的结构如下:
-
1、认识正则表达式 -
2、匹配规则 -
3、复杂匹配规则 -
4、分组分配 -
5、非贪婪匹配 -
6、分割、查找、替换、反向引用
1、认识正则表达式
-
正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串,通常被用来检索、替换那些符合某个模式(规则)的文本。下面通过一个简单的例子来认识下正则表达式。
public class MatchesDemo1 {
/**
* 正则表达式简介
* @param args
*/
public static void main(String[] args) {
/**
* 判断用户输入的年份为20##年,规则如下:
* 一共4个字符,分别是2,0,0-9任意数字,0-9任意数字
* 对应的正则表达式就是:20\d\d,其中\d表示任意一个数字
* 把正则表达式转化为java字符串就变成了“20\\d\\d”,java字符串用“\\”表示“\”
*/
String regex = "20\\d\\d";
System.out.println("2017".matches(regex)); //true
System.out.println("2100".matches(regex)); //false
}
}
2、匹配规则
public class 匹配规则 {
/**
* 正则表达式的匹配规则是从左到右匹配,
* 如果正则表达式中有特殊字符,要用“\”来转义,如“\&”用来匹配特殊字符“&”
* 要注意的是,正则表达式在Java中也是一个字符串,因此,对于正则表达式“a\&c”对应的Java字符串应该是“a\\&c”,
* 因为“\”也是Java字符的转义字符,两个“\\”实际上表示的是“\”
* 如果想要匹配非ASCII字符,例如中文,用Unicode编码如:你好 \u4f60\u597d
* @param args
*/
public static void main(String[] args) {
test7();
}
static void test1(){
String re1 = "abc";
System.out.println("abc".matches(re1));//true
System.out.println("Abc".matches(re1));//false
System.out.println("ABC".matches(re1));//false
String re2 = "a\\&c";
System.out.println("a&c".matches(re2));//true
System.out.println("a-c".matches(re2));//false
System.out.println("a&&c".matches(re2));//false
System.out.println("你好".matches("\u4f60\u597d"));//true
}
/**
* 匹配任意字符
* 用“.”匹配一个任意字符
*/
static void test2(){
System.out.println("a*9".matches("a.9"));//true
}
/**
* 匹配数字
* \d可以匹配0-9的任意数字
*/
static void test3(){
System.out.println("ab9".matches("ab\\d"));//true
}
/**
* 匹配常用字符
* \w可以匹配一个字母、数字、下划线,w的意思是word
*/
static void test4(){
System.out.println("a3".matches("\\w3"));//true
System.out.println("A3".matches("\\w3"));//true
System.out.println("03".matches("\\w3"));//true
System.out.println("_3".matches("\\w3"));//true
}
/**
* 匹配空格字符
* \s匹配空格包括空格和tab字符(在Java中用\t表示)
*/
static void test5(){
System.out.println("a\tb".matches("a\\sb"));//true
System.out.println("a b".matches("a\\sb"));//true
}
/**
* 匹配非数字
* \d匹配数字,\D匹配非数字
* 类似的,\W可以匹配\w不能匹配的字符,\S可以匹配\s不能匹配的字符
*/
static void test6(){
System.out.println("a0".matches("a\\D")); //false
System.out.println("ab".matches("a\\D"));//true
System.out.println("aB".matches("a\\D"));//true
System.out.println("a_".matches("a\\D"));//true
System.out.println("a*".matches("a\\D"));//true
}
/**
* 重复匹配
* 修饰符”*“可以匹配任意个字符,包括0个、1个、多个,相当于{0,}
* 修饰符”+“可以匹配至少一个字符 包括1个、多个
* 修饰符”?“可以修饰0个或者1个字符
* {n}精确指定几个字符
* {n,m}指定匹配n~m个字符
* {n,}为至少匹配n个字符
*/
static void test7(){
System.out.println("A234".matches("A\\d{2,}"));//true
}
}
3、复杂匹配规则
public class 复杂匹配规则 {
public static void main(String[] args) {
test4();
}
/**
* 匹配开头和结尾
* 正则表达式多行匹配时,我们用"^"表示开头,”$“表示结尾
*/
static void test1(){
String str = "A\\d{3}$";
System.out.println("A009".matches(str));//true
System.out.println("A123".matches(str));//true
}
/**
* 匹配指定范围
*
* 使用[……]可以匹配范围内的字符,如[123456789]可以匹配1~9,但是把所有的字符全列出来有点麻烦,
* [……] 还有一种写法,[1-9]
* 要匹配大小写不限的十六进制数,如1A2b3c,我们可以这样写[0-9a-fA-F]
* 匹配6位的16进制数可以写[0-9a-fA-F]{6}
*
* [...]还有一种排除法,即不包含指定范围的字符,假设我们要匹配任意字符,但不包含数字,可以写[^0-9]{3}
*/
static void test2(){
}
/**
* 或规则匹配
*
* 用"|"连接的两个正则规则是或规则,如ab|cd可以匹配ab或cd
*/
static void test3() {
String re = "html|css|js";
System.out.println("html".matches(re)); //true
System.out.println("css".matches(re));//true
System.out.println("js".matches(re));//true
}
/**
* 使用括号
* 现在要进行匹配learn html、learn css 、learn js ,要是用learn\shtml|learn\scss|learn\sjs就太麻烦了,我们可以把公共部分提出来
* 然后用(。。。)把子规则括起来表示成learn\s(java|php|go)
*/
static void test4(){
String re = "learn\\s(html|css|js)";
System.out.println("learn html".matches(re));//true
System.out.println("learn css".matches(re));//true
System.out.println("learn js".matches(re));//true
}
}
4、分组分配
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class 分组分配 {
public static void main(String[] args) {
test1();
}
/**
* 问题:010-4657858这样的电话号码,如何判断后还方便将区号和号码分别提取出来呢?
*引入java.util.regex包,用Pattern对象匹配,匹配后获得一个Matcher对象,如果匹配成功,就可以直接从Matcher.group(index)返回字串。
*
* Matcher.group(index)方法的参数用1表示第一个子串,2表示第二个子串。如果我们传入0会得到什么呢?答案是010-12345678,即整个正则匹配到的字符串。
*
* 使用Matcher时,必须首先用mather判断,为true时,才可以调用group获取字串
* String。matches()方法内部调用的就是Pattern和Matcher类的方法
*/
static void test1(){
Pattern p = Pattern.compile("(\\d{3,4})\\-(\\d{7,8})");
Matcher m = p.matcher("010-1234567");
if (m.matches()) {
String group1 = m.group(1);
String group2 = m.group(2);
String group0 = m.group(0);
System.out.println(group1); //010
System.out.println(group2); //1234567
System.out.println(group0); //010-1234567
}else {
System.out.println("匹配失败!");
}
}
}
5、非贪婪匹配
匹配次数中的贪婪模式(匹配字符越多越好,默认)
匹配次数中的非贪婪模式(匹配字符越少越好,修饰匹配次数的特殊符号后再加上一个“?”号)
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 本接任务:区分?的含义,\d??
*/
public class 非贪婪匹配 {
public static void main(String[] args) {
test1();
test2();
test3();
}
/**
* 下面的这个例子:
* 我们是期望获得123 和00000这两个的,结果group1结构就是12300000而group2是空字符串,
* 得到这个结果也可以理解吧,因为\d+把后面的0也包括进来了
* 为了让\d+尽可能的少匹配,0*尽可能多的多匹配,我们使用非贪婪匹配,在\d后加上?
*/
static void test1(){
Pattern pattern = Pattern.compile("(\\d+)(0*)");
Matcher matcher = pattern.matcher("12300000");
if (matcher.matches()) {
System.out.println("group1="+matcher.group(1)); //group1=12300000
System.out.println("group2="+matcher.group(2)); //group2=
}
}
static void test2(){
Pattern pattern = Pattern.compile("(\\d+?)(0*)");
Matcher matcher = pattern.matcher("12300000");
if (matcher.matches()) {
System.out.println("group1="+matcher.group(1)); //group1=123
System.out.println("group2="+matcher.group(2)); //group2=00000
}
}
static void test3(){
Pattern pattern = Pattern.compile("(\\d??)(9*)");
Matcher matcher = pattern.matcher("1999999999");
if (matcher.matches()) {
System.out.println("group1="+matcher.group(1)); //group1=1
System.out.println("group2="+matcher.group(2)); //group2=999999999
}
}
}
6、分割、查找、替换、反向引用
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class SearchAndReplace {
public static void main(String[] args) {
test1();
test2();
test3();
test4();
}
/**
* 分割字符串
* 使用正则表达式分割字符串可以实现更加灵活的功能,String.split()方法传入的是正则表达式,
* 如果我们想让用户传入一组标签,然后将标签提取出来,因为用户的输入往往是不规范的,如果我们使用合适的
* 正则表达式就可以消除多个空格、混合“,”“;”等不规范的输入,直接提取出规范的字符串
*/
static void test1(){
String[] split = "a b c".split("\\s"); //[a, b, c]
System.out.println(Arrays.asList(split));
String[] split1 = "a b c".split("\\s"); //[a, b, , , , c]
System.out.println(Arrays.asList(split1));
String[] split2 = "a,b ;; , c".split("[\\,\\;\\s]+");//[a, b, c]
System.out.println(Arrays.asList(split2));
}
/**
* 搜索字符串
*/
static void test2(){
String s = "the quick brown fox jumps over the lazy dog.";
Pattern p = Pattern.compile("\\wo\\w");
Matcher m = p.matcher(s);
while (m.find()) {
String substring = s.substring(m.start(), m.end());
System.out.println(substring);
}
//row
//fox
//dog
}
/**
* 替换字符串
*
* 正则表达式替换字符串可以直接调用String。replaceAll(),它的第一个参数是正则表达式,第二个参数式待替换的字符串
*/
static void test3(){
String s = "The quick\t\t brown fox jumps over the lazy dog.";
String r = s.replaceAll("\\s+", " ");
System.out.println(r); // "The quick brown fox jumps over the lazy dog."
}
/**
* 反向引用
* 如果我们要把搜索到的指定字符串按规则替换,比如前后各加一个<b>xxxx</b>,这个时候,使用replaceAll()的时候,我们传入的第二个参数可以使用$1、$2来反向引用匹配到的子串
*/
static void test4(){
String s = "the quick brown fox jumps over the lazy dog.";
String r = s.replaceAll("\\s([a-z]{4})\\s", " <b>$1</b> ");
System.out.println(r); //the quick brown fox jumps <b>over</b> the <b>lazy</b> dog.
}
}
欢迎转载,转载请注明原文出处@hellotqq 个人公众号 :hellotqq, gitee:hellotqq(常用) github:hellotqq(不常用) CSDN:hellotqq 稀土掘金:hellotqq 博客园:hellotqq 欢迎关注交流与您共同成长!
作者介绍
h
hellotqq
V1