正则表达式的学习心得

一、正则表达式说明

​ 正则表达式是针对字符串的提取,所有语言都支持,不管是前端的JS还是后端PHP,还包含了测试工具Jmeter,SQL,Linux上的find等等,对于开发来说,很重要,并且掌握后对一些字符工具操作会很方便

​ 正则表达式主要是使用各类符号或者字母来表达,用到的符号看似很多,但有些符号是从另外的符号中扩展而来的,比如想要匹配一个数字时可以使用 [0-9] ,也可以用\d来简化写法,\d就是扩展用来匹配数字的。扩展的符号多了看上去匹配词就感觉很多,实则先学习它基本的匹配词后再去记扩展词就会容易很多。

​ 学习正则的时候可以将使用到的符号就行分为几大类,先从基础的匹配到复杂的提取,层级递进从而达到螺旋式上升。比如[0-9]代表匹配0到9数字;{2}代表至少满足两次前面的字符,连起来就是[0-9]{2}就是一个正则表达式,能匹配到的长度为2的数字;^ 代表开头,连起来就是^[0-9]{2},匹配以两位数字开头字符。

二、正则语法

首先我将正则使用到的符号分为几大类:匹配符、限定符、定位符、装饰符和运算符号的优先级来就行练习,逐一掌握

2.1、字符匹配

在一串字符中,想要匹配数字、字母或者是符号,我们就可以根据这些特性然后使用特定的字符来做匹配提取

字符 说明
. 匹配所有单个字符,除了\r\n
| 或者,当表达式中出现非关键字的字符时就代表需匹配该字符。使用`
[] 包含其中的一个字符,例如[abc]匹配"are"里的a
- 字符范围。匹配指定范围内的任何字符。例如,[a-z]匹配"a"到"z"范围内的任何小写字母。
[^] ^与[]搭配是反向匹配。匹配未包含的字符,例如[^abc] 匹配非abc的字符,还能反向范围[^a-b]
\n 换行符匹配
\f 换页符匹配
\r 匹配一个回车符
\v 垂直制表符匹配
\ 转义符,标记下一个字符标记为特殊字符

如上是基础的字符匹配,为了简化表达式,又就行了一些常用的匹配做了扩展,于是有了

字符 说明
\d 匹配数字,等效于[0-9]
\D 匹配非数字,等效与[^0-9]
\w 匹配任何字类字符,包括下划线。等效[A-Za-z0-9_]
\W 与任何非单词字符匹配。与[^A-Za-z0-9_]等效。可以用来找符号。
\s 匹配任何空白字符,包括空格、制表符、换页符等。与 [ \f\n\r\t\v] 等效。
\S 匹配任何非空白字符。与 [^\f\n\r\t\v] 等效。

2.2、限定符

一个匹配符一次只能匹配一个符号,那么要匹配多少个也需要指定,也就是限定符。

字符 说明
{n} n是正整数,代表着正好匹配n次,例如a{3} 匹配到的是aaa, aa匹配不到
{n,} n是正整数,代表匹配n或者n次以上,
{n,m} n和m是正整数且n <= m,代表着匹配至少n次,最多m次
* 零次或多次匹配。例如,zo* 匹配"z"和"zoo"。* 等效于 {0,}。
+ 一次或多次匹配前面的字符或子表达式。例如,"zo+"与"zo"和"zoo"匹配,但与"z"不匹配。+ 等效于 {1,}。
? 零次或一次匹配前面的字符或子表达式。例如,"do(es)?“匹配"do"或"does"中的"do”。? 等效于 {0,1}。
??或者+? 当此字符(?)在任意限定符的后面时,它的作用不再是限定符了,而是将匹配模式换成”非贪心“,这种模式是将匹配到的字符尽可能的短。例如o+ 在oooooo匹配到的是全部,使用o{2,}?则会只匹配到前两个o

2.3、定位符

在一串字符中,可以规定从哪里开始匹配,比如开头,或者结尾

字符 说明
^ 匹配字符的开始位置
$ 匹配字符的结束位置
\b 匹配一个字边界,代表单词的开头或者结尾,单词之间由标点符号或者空格来分隔,但\b不会认为用逗号分割的为边界。需要配合匹配符来使用例如:\ba 匹配开头的a; [1-9]\b 以数字结尾的
\B 匹配非边界字符。

2.4、优先符顺序说明

正则表达式从左开始运算,并遵循优先级顺序,和算数表达式类似。优先级如下,高到低

字符 描述
\ 转义符
(),[],(? 圆括号和方括号
*,+,?,{} 限定符
^,$,\普通字符,普通字符 定位符和匹配符
| 或者

2.5、装饰符

正则表达式的标记用于指定额外的匹配策略。

//Java写法如下,其他的不知道
Pattern pattern = Pattern.compile("(?i)Java");
字符 描述
i ignore的缩写,代表不区分大小写
g global的缩写,代表全局匹配
m multi line 多行匹配
s . 匹配所有单个字符除\r\n,使用s则可以匹配\n

三、在Java中使用正则

java.util.regex是一个用正则表达式对字符串就行匹配工作的类库包,它包括了两个类:Pattern和Matcher。

1、Pattern

Pattern类用于创建一个正则表达式,也可以说是创建一个匹配模式

1.1、compile(String regex)

静态方法创建Pattern对象,regex为正则表达式

Pattern pattern = Pattern.compile("Java");
// 返回此模式的正则表达式即Java
System.out.println(pattern.pattern());
1.2、compile(String regex,int flags)

静态方法创建Pattern对象,regex为正则表达式,flags为可选模式,如:Pattern.CASE_INSENSITIVE 忽略大小写;Pattern.DOTALL此模式下 .会匹配换行符,默认匹配模式下 .不会匹配换行符。等等,具体可参照Pattern的多种匹配模式。

Pattern pattern = Pattern.compile("Java", Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher("java");
//返回true,如果使用默认匹配规则则为false
System.out.println(matcher.matches());
参数 说明
Pattern.CASE_INSENSITIVE 忽略大小写
Pattern.DOTALL . 匹配所有单个字符除\r\n,使用s则可以匹配\n
Pattern.MULTILINE 开启多行匹配,^ $在默认的情况下只会匹配第一行,设置了MULTILINE模式回匹配所有行。
1.3、matches(String regex, CharSequence input)

静态方法,判断input 是否匹配给定的正则表达式,注意的是该方法适合用于只匹配一次,且匹配全部字符串

//返回true
Pattern.matches("\\d+","2223");
//返回false,需要匹配到所有字符串才能返回true,这里aa不能匹配到
Pattern.matches("\\d+","2223aa");
1.4、split(CharSequence input)

用于分隔字符串,并返回一个String[]

Pattern compile = Pattern.compile("\\d+");
//abc,def,g
String[] strArray = compile.split("abc1231def3g");

2、Matcher

匹配器,对正则表达式的分组支持,以及对正则表达式的多次匹配支持,需要调用 Pattern 对象的 matcher 方法来获得一个 Matcher 对象。

2.1、matches()

整个字符进行匹配,只有整个字符序列完全匹配成功才返回true。

Pattern compile = Pattern.compile("\\d*");
Matcher matcher = compile.matcher("123a");
boolean status = matcher.matches();
2.2、索引方法start()和end()

在调用匹配方法时,会移动指针到匹配词所在字符的索引,默认是在0位置上,start为初始索引,end为所在的索引之后的一个偏移量。

Pattern pattern = Pattern.compile("\\d+");
Matcher matcher = pattern.matcher("123dfdf3424r");
boolean status = matcher.find();
if (status){
    // 0
	System.out.println(matcher.start());
    // 3
	System.out.println(matcher.end());
}
2.3、lookingAt

部分匹配,从第一个字符进行匹配,符合返回true并且不再继续匹配,失败了也不再继续匹配直接返回false。

Pattern compile1 = Pattern.compile("\\d");
//返回true
Matcher matcher1 = compile1.matcher("123");
//返回false
Matcher matcher2 = compile1.matcher("d123");

//返回false
Pattern compile2 = Pattern.compile("\\d{1,3}");
Matcher matcher = compile.matcher("ddds123");


//返回false
Pattern compile = Pattern.compile("\\d{1,3}");
Matcher matcher = compile.matcher("ddds123");
2.4、find()和find(int start)

部分匹配,从当前位置开始匹配,找到一个匹配的子串,将移动下次匹配的位置。也可以使用find(int start)方法,从指定位置开始匹配

2.5、reset()

前面调用匹配方法,指针会移动,使用reset()将指针重置为0

2.6、groupCount()

返回该正则表达式中的子序列,就是以()圈起来的表达式数量,不是计算匹配数

Pattern compile = Pattern.compile("(\\d[abc])a(\\d([a]3))");
Matcher matcher = compile.matcher("123abc45b6");
//这里可以简化成()(()),总共有三对口括号,所以为3
System.out.println("找到-->"+matcher.groupCount());
2.7、grop()和grop(int grop)

当匹配到一串字符的时候,它可能是由多个子序列匹配构成的,使用grop()是获取到完整匹配字符,grop(0)等同与grop(),grop(int grop)是获取指定子序列匹配的字符

String line = "123ra9040";
String pattern = "(\\d+)([a-z]+)(\\d+)";

Pattern r = Pattern.compile(pattern);
Matcher m = r.matcher(line);

while (m.find( )) {
    //获取完整的匹配字符->123ra9040
    System.out.println("Found value: " + m.group(0) );
    //获取(\\d+)匹配到->123
    System.out.println("Found value: " + m.group(1) );
    //获取([a-z]+)匹配到->ra
    System.out.println("Found value: " + m.group(2) );
    //获取
    System.out.println("Found value: " + m.group(3) );
}

括号嵌套先找范围小的括号,如下:


Pattern compile = Pattern.compile("((\\d[abc])b)");
Matcher matcher = compile.matcher("123abc45b6");

while (matcher.find()){
    //3ab
	System.out.println(matcher.group());
    //((\\d[abc])b) 3ab
	System.out.println(matcher.group(1));
    // (\\d[abc])  3a
	System.out.println(matcher.group(2));
}

grop(int grop) 中,grop范围可以使用groupCount()方法来确定子序列个数

四、常见的怎则表达式

#纯数字
^[0-9]*$


#n位数字
^\d{n}$

#只能输入汉字
^[\u4e00-\u9fa5]{0,}$ 

#邮箱
\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*

# 匹配网址URL的正则表达式
[a-zA-z]+://[^\s]*

# 手机号
/^1(3\d|4[5-9]|5[0-35-9]|6[567]|7[0-8]|8\d|9[0-35-9])\d{8}$/

参考文献

https://blog.csdn.net/weixin_43501172/article/details/115655288

## 匹配模式
https://blog.csdn.net/BaymaxCS/article/details/119281231

https://www.cnblogs.com/54chensongxia/archive/2020/12/16/14145325.html

https://www.runoob.com/regexp/regexp-syntax.html

你可能感兴趣的:(Java基础,正则表达式,java,爬虫)