正则表达式
作用:
- 校验字符串是否满足规则
- 在一段文本中查找满足要求的内容
字符类(只匹配一个字符)
说明 | |
---|---|
[abc] | 只能是a,b或c |
[^abc] | 除了a,b,c之外的任何字符 |
[a-zA-Z] | a 到 z, A 到 Z(范围) |
[a-d[m-p]] | a 到 d, 或 m 到 p |
[a - z && [def]] | a 到 z和def的交集。为: d, e, f |
[a - z && [^bc]] | a 到 z和非bc的交际 ( 等同于[ad-z] ) |
[a-z&&[^m-p]] | a 到 z和除了m到p的交集 |
Demo:
public class RegexDemo1 {
public static void main(String[] args) {
System.out.println("-------------1----------------");
String str1 = "a";
System.out.println(str1.matches("[abc]"));//true
System.out.println(str1.matches("[a-c]"));//true
System.out.println(str1.matches("[^a-c]"));//true
System.out.println("ab".matches("[a-c]"));//false 原因: [a-c]只能匹配一个,有两个字符要去匹配两次
System.out.println("ab".matches("[a-c][a-c]"));//true
System.out.println("-------------2----------------");
System.out.println("n".matches("[a-d[m-p]]"));//true
System.out.println("nn".matches("[a-d[m-p]]"));//false
System.out.println("nn".matches("[a-d[m-p]][a-d[m-p]]"));//true
System.out.println("-------------3----------------");
//如果要表示两个范围的交集, 要用 &&
//如果只写一个 & ,则仅仅是表示一个字符 &
System.out.println("a".matches("[a-z&&[def]]"));//false
System.out.println("d".matches("[a-z&&[def]]"));//true
System.out.println("a".matches("[a-z&[def]]"));//true
System.out.println("-------------4----------------");
System.out.println("a".matches("[a-z&&[^def]]"));//true
System.out.println("d".matches("[a-z&&[^def]]"));//false
}
}
预定义字符(只匹配一个字符)
表达式 | 字符 |
---|---|
. | 任何字符 |
\d | 一个数字: [0-9] |
\D | 非数字: [^0-9] |
\s | 一个空白字符: [\t\n\x0B\f\r] |
\S | 非空白字符: [^\s] |
\w | [a-zA-Z_0-9]英文、数字、下划线 |
\W | [^\w]一个非单词字符 |
Demo:
public class RegexDemo2 {
public static void main(String[] args) {
System.out.println("-------------1----------------");
//.表示一个任意字符
System.out.println("你".matches("."));//true
System.out.println("你n".matches("."));//false
System.out.println("你n".matches(".."));//true
System.out.println("-------------2----------------");
// \d表示一个数字
System.out.println("9".matches("\\d"));//true
System.out.println("a".matches("\\d"));//false
System.out.println("99".matches("\\d"));//false
System.out.println("99".matches("\\d\\d"));//true
System.out.println("-------------3----------------");
// \D 表示非数字
System.out.println("9".matches("\\D"));//false
System.out.println("a".matches("\\D"));//true
System.out.println("ab".matches("\\D"));//false
System.out.println("ab".matches("\\D\\D"));//true
System.out.println("-------------3----------------");
// \s一个空白字符
System.out.println("\t".matches("\\s"));//true
System.out.println("\t\t".matches("\\s"));//false
System.out.println(" ".matches("\\s"));//true
System.out.println(" ".matches("\\s"));//false
System.out.println("9".matches("\\s"));//false
System.out.println("a".matches("\\s"));//false
System.out.println("-------------4----------------");
// \S非空白字符
System.out.println("\t".matches("\\S"));//false
System.out.println(" ".matches("\\S"));//false
System.out.println("a".matches("\\S"));//true
System.out.println("9".matches("\\S"));//true
System.out.println("-------------5----------------");
// \w [a-zA-Z_0-9]英文、数字、下划线
System.out.println("a".matches("\\w"));//true
System.out.println("A".matches("\\w"));//true
System.out.println("0".matches("\\w"));//true
System.out.println("_".matches("\\w"));//true
System.out.println("-------------5----------------");
// \W 一个非单词字符
System.out.println("&".matches("\\W")); //true
System.out.println("a".matches("\\W")); //false
System.out.println("A".matches("\\W")); //false
System.out.println("0".matches("\\W")); //false
System.out.println("_".matches("\\W")); //false
}
}
数量词(表中的 ‘X’ 代表任意内容)
表达式 | 说明 |
---|---|
X? | X,一次或0次 |
X* | X,零次或多次 |
X+ | X,一次或多次 |
X{n} | X,正好n次 |
X{n, } | X,至少n次 |
X{n, m} | X,至少n次但不超过m次 |
Demo:
public class RegexDemo3 {
public static void main(String[] args) {
System.out.println("a".matches("[abc]?"));//true 一次或0次
System.out.println("".matches("[abc]?"));//true
System.out.println("aaa".matches("[abc]*"));//true 零次或多次
System.out.println("".matches("[abc]*"));//true
System.out.println("".matches("[abc]+"));//false 一次或多次
System.out.println("a".matches("[abc]+"));//true
System.out.println("aa".matches("[abc]+"));//true
System.out.println("aaa".matches("[abc]{3}"));//true 刚好三次
System.out.println("aaaa".matches("[abc]{3}"));//false
System.out.println("aa".matches("[abc]{3}"));//false
System.out.println("aa".matches("[abc]{3,}"));//false 至少三次
System.out.println("aaa".matches("[abc]{3,}"));//true
System.out.println("aaaa".matches("[abc]{3,}"));//true
System.out.println("aaa".matches("[abc]{3,4}"));//true//至少三次但不超过四次
System.out.println("aaaa".matches("[abc]{3,4}"));//true
System.out.println("aa".matches("[abc]{3,4}"));//false
System.out.println("aaaaa".matches("[abc]{3,4}"));//false
}
}
爬虫
正则表达式的对象:Pattern
文本匹配器对象:Matcher
Pattern常见方法:
(待完善)
Matcher常见方法:
(待完善)
方法名 | 说明 |
---|---|
find() | 拿着文本匹配器从头开始读取, 寻找是否有满足规则的字符串.如果没有,方法返回false,如果有,返回true |
m.group() | 该方法底层会根据find方法记录的索引进行字符串的截取,会把截取的小字符串进行返回 |
Demo1:
package RegexDemo;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class crawler {
public static void main(String[] args) {
/*有如下文本,请按照要求爬取数据。
Java自从95年问世以来,经历了很多版本,目前企业中用的最多的是ava8和ava11,
因为这两个是长期支持版本,下一个长期支持版本是Java17,相信在未来不久Java17也会逐渐登上历史舞台
要求:找出里面所有的JavaXX
*/
String str = "Java自从95年问世以来,经历了很多版本,目前企业中用的最多的是Java8和Java11," +
"因为这两个是长期支持版本,下一个长期支持版本是Java17,相信在未来不久Java17也会逐渐登上历史舞台";
// method1(str);
//1.获取正则表达式的对象,也就是Pattern的对象
Pattern p = Pattern.compile("Java\\d{0,2}");
//2.获取文本匹配器的对象
Matcher m = p.matcher(str);
//3.利用循环
while (m.find()){
String s = m.group();
System.out.println(s);
}
}
private static void method1(String str) {
//Pattern: 表示正则表达式
//Matcher: 文本匹配器,作用按照正则表达式的规则去读取字符串,从头开始读取。在大串中去找符合匹配规则的子串。
//1.获取正则表达式的对象,也就是Pattern的对象
Pattern p = Pattern.compile("Java\\d{0,2}");
//2.获取文本匹配器的对象
//m: 文本匹配器的对象
//str: 大的字符串
//p: 规则
//m要在str中找符号p规则的小的字符串
Matcher m = p.matcher(str);
//拿着文本匹配器从头开始读取, 寻找是否有满足规则的字符串
//如果没有,方法返回false
//如果有,返回true,在底层记录子串的起始索引和结束索引+1
boolean b = m.find();
//该方法底层会根据find方法记录的索引进行字符串的截取
//会把截取的小字符串进行返回
String s1 = m.group();
System.out.println(s1);
}
}
Demo2:
package RegexDemo;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class crawlerTwo {
public static void main(String[] args) {
String s = "Java自从95年问世以来,经历了很多版本,目前企业中用的最多的是java8和Java11," +
"因为这两个是长期支持版本,下一个长期支持版本是Java17,相信在未来不久Java17也会逐渐登上历史舞台";
//定义正则表达式
//? 理解为前面的数据Java
//= 表示后面要跟随的数据
//但是在获取的时候只获取前半部分
// (?i) : 忽略大小写
String regex1 = "((?i)Java)(?=8|11|17)";
//下面两个效果相同
//使用 " : " 时获取数据的时候获取全部
String regex2 = "((?i)Java)(8|11|17)";
String regex3 = "((?i)Java)(?:8|11|17)";
//去掉Java后面后 8/11/17 的数据
String regex4 = "((?i)Java)(?!8|11|17)";
Pattern p = Pattern.compile(regex1);
Matcher m = p.matcher(s);
while (m.find()) {
System.out.print(m.group() + " ");
}
System.out.println();
Pattern p1 = Pattern.compile(regex2);
Matcher m1 = p1.matcher(s);
while (m1.find()) {
System.out.print(m1.group() + " ");
}
System.out.println();
Pattern p2 = Pattern.compile(regex3);
Matcher m3 = p2.matcher(s);
while (m3.find()) {
System.out.print(m3.group() + " ");
}
System.out.println();
Pattern p3 = Pattern.compile(regex4);
Matcher m4 = p3.matcher(s);
while (m4.find()) {
System.out.print(m4.group() + " ");
}
}
}
Demo3:
package RegexDemo;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class crawlerThree {
public static void main(String[] args) {
/*需求1∶按照ab+的方式爬取ab,b尽可能多获取
需求2:按照ab+的方式爬取ab,b尽可能少获取
*/
String s ="Java自从95年问世以来,abbbbbbbbbbbbaaaaaaaaaaaaaaaaaa" +
"经历了很多版本,目前企业中用的最多的是Java8和Java11,因为这两个是长期支持版本,下一个长期支持版本是Java17,相信在未来不久Java17也会逐渐登上历史舞台";
//贪婪爬取 (Java默认)
String regex = "ab+";
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(s);
while (m.find()){
System.out.println(m.group());
}
//非贪婪爬取 (在 " + " 后面加一个问号就行了)
String regex1 = "ab+?";
Pattern p2 = Pattern.compile(regex1);
Matcher m2 = p2.matcher(s);
while (m2.find()){
System.out.println(m2.group());
}
}
}
正则表达式在字符串方法中的使用:
方法名 | 说明 |
---|---|
matches(String regex) | 判断字符串是否满足正则表达式规则 |
replaceAll(String regex, String newstr) | 按照正则表达式规则进行替换 |
split(String regex) | 按照正则表达式的规则切割字符串 |
Demo4:
package RegexDemo;
public class crawlerFour {
public static void main(String[] args) {
/*有一段字符串:小诗诗dqwefqwfqwfwq12312小丹丹dqwefqwfqwfwq12312小惠惠
要求1:把字符串中三个姓名之间的字母替换为vs
要求2:把字符串中的三个姓名切割出来
*/
String s = "小诗诗dqwefqwfqwfwq12312小丹丹dqwefqwfqwfwq12312小惠惠";
String result1 = s.replaceAll("[\\w && [^_]]+", "vs");
System.out.println(result1);
String[] s1 = s.split("[\\w &&[^_]]+");
for (int i = 0; i < s1.length; i++) {
System.out.println(s1[i]);
}
}
}
最后:欢迎大家关注我的公众号