import java.util.regex.Pattern 正则表达式包
import java.util.regex.Matcher 文本匹配器包
作用1 :正则表达式可以校验字符串是否满足一定的规则,并用来校验数据格式的合法性。
作用2 :正则表达式可以在一段文字中查找满足要求的内容。
常用方法
public String[ ] matches(String regex) //判断是否与正则表达式匹配
public String replaceAll(String regex,String newStr) //按照正则表达式的规则进行替换
public String[ ] spilt(String regex) //按照正则表达式的规则进行切割字符串
一、校验字符串

1.1、字符类(只匹配一个字符)

注意:和用&&,或用|
public class matchesTest {
public static void main(String[] args) {
// 一个大括号只能是一个字符
// 只能是a b c
System.out.println("a".matches("[abc]")); // true
System.out.println("z".matches("[abc]")); // false
System.out.println("ab".matches("[abc]")); // false
System.out.println("ab".matches("[abc][abc]")); // true
// 不能出现a b c
System.out.println("a".matches("[^abc]")); // fasle
System.out.println("zz".matches("[^abc]")); // fasle
// a到z A到Z(包括头尾范围)
System.out.println("b".matches("[a-zA-Z]")); // true
System.out.println("0".matches("[a-zA-Z]")); // fasle
// [a-d[m-p]] a到d 或者 m到p
System.out.println("b".matches("[a-d[m-p]]")); // true
System.out.println("e".matches("[a-d[m-p]]")); // fasle
// [a-z&&[def]] a-z和def的交集
// 细节:如果要求两个范围的交集 需要写&&
// 如果写成了一个& 就不表示交集 只是单单一个符号而已
System.out.println("a".matches("[a-z&&[def]]")); // true
System.out.println("&".matches("[a-z&&[def]]")); // false
// [a-z&&[^bc]] a-z 和 非bc 的交集
System.out.println("a".matches("[a-z&&[^bc]]")); // true
System.out.println("b".matches("[a-z&&[^bc]]")); // false
// [a-z&&[^m-p]] a到z和除了m到p的交集
System.out.println("a".matches("[a-z&&[^m-p]]")); // true
System.out.println("m".matches("[a-z&&[^m-p]]")); // false
}
}
1.2、预定义字符预定义字符(只匹配一个字符)

public class matchesTest {
public static void main(String[] args) {
// \表示转义字符 :改变后面字符原本含义
// 练习:以字符串形式打印一个双引号
// System.out.println("\"");
// .表示任意一个字符
System.out.println("你".matches(".")); // true
System.out.println("你a".matches("..")); // true
// \\d 只能是任意一个数字
// 简单来说 两个\表示一个\
System.out.println("a".matches("\\d")); // fasle
System.out.println("3".matches("\\d")); // true
System.out.println("333".matches("\\d")); // fasle
System.out.println("333".matches("\\d\\d\\d")); // true
// \\w只能是一个单词字符 [a-zA-Z0-9]
System.out.println("z".matches("\\w")); // true
System.out.println("21".matches("\\w")); // false
System.out.println("你".matches("\\w")); // fasle
System.out.println("-".matches("\\w")); // true
// 非单词字符
System.out.println("你".matches("\\W")); // true
// 以上正则表达式只能校验单个字符
}
}
1.3、数量词

public class matchesTest {
public static void main(String[] args) {
//必须是数字 字母 下划线 至少 6位
System.out.println("2442fsfsf".matches("\\w{6,}")); //true
System.out.println("244f".matches("\\w{6,}")); //false
//必须是数字和字符 必须是 4位
System.out.println("23dF".matches("[a-zA-Z0-9]{4}")); //true
System.out.println("23_F".matches("[a-zA-Z0-9]{4}")); //false
System.out.println("23dF".matches("\\w&&[^_]{4}")); //true
System.out.println("23_F".matches("\\w&&[^_]{4}")); //fasle
}
}
1.4、练习
public class matchesTest {
public static void main(String[] args) {
//手机号: 三部分
//一、 1 表示手机号码只能由1开头
//二、 [3-9] 表示手机号码第二位只能是3-9之间
//三、\\d{9} 表示任意数字可以出现9次,也只能出现9次
String regex1 = "1[3-9]\\d{9}";
System.out.println("13112345678".matches(regex1)); //true
System.out.println("131123456789".matches(regex1)); //fasle
//座机号码: 三部分
//一、区号: 0表示区号只能以0开头
// \\d{2,3} 表示区号从二位开始可以是任意数字,可以出现2~3次
//二、 - ?表示次数 次数0次或者1次
//三、 号码 第一位不能以0开头;从第二位开始可以为任意数字 ;号码总长度: 5-10位
String regex2 = "0\\d{2,3}-?[1-9]\\d{4,9}";
System.out.println("020-2324242".matches(regex2)); //true
//邮箱号码 :三部分
//一、 @左边 \\w+任意字符数字下划线至少出现一次就行
//二、 @只能出现一次
//三、 .的左边可以是字母和数字 [\\w&&[^_]] 任意字符数字总共出现2-6次 {2,6}
// . \\.
// .的右边 所有的大写字母和小写字母 只能出现2-3次 [a-zA-Z]{2,3}
String regex3 = "\\w+@[\\w&&[^_]]{2,6}\\.[a-zA-Z]{2,3}";
System.out.println("zhangsan@163.com".matches(regex3)); //true
//24小时
String regex4 = "([01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d";
System.out.println("23:11:11".matches(regex4)); //true
String regex5 = "([01]\\d|2[0-3])(:[0-5]\\d){2}";
System.out.println("23:11:11".matches(regex5)); //true
}
}
public class RegexDemo11 {
public static void main(String[] args) {
//public String replaceAll(String regex,String newStr) 按照正则表达式的规则进行替换
//public String[] split(String regex): 按照正则表达式的规则切割字符串
/*
有一段字符串:小诗诗dqwefqwf qfwfq12312小丹丹dqwefqwf qfwfq12312小惠惠
要求1:把字符串中三个姓名之间的字母替换为vs
要求2:把字符串中的三个姓名切割出来
*/
String s = "小诗诗dqwefqwf qfwfq12312小丹丹dqwefqwf qfwfq12312小惠惠";
//细节:
//方法在底层跟之前一样也会创建文本解析器的对象
//然后从头开始去读取字符串中的内容,只要有满足的,那么就用第二个参数去替换。
//String resut1 = s.replaceAll("[\\w&[^^]]+", "vs");
//System.out.println(resut1);
String[] arr = s.split("[\\w&[^^]]+");
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}
二、爬虫
2.1、本地爬虫
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class regexTest {
public static void main(String[] args) {
String str = " Java自从95年问世以来,经历了很多版本,目前企业中用的最多的是"
+ "Java8和Java11,因为这两个是长期支持版本,下一个长期支持版本是Java17,"
+ "相信在未来不久Java17也会逐渐登上历史舞台。";
// 需求:找出里面所有的JavaXX
// 获取正则表达式对象
Pattern p = Pattern.compile("Java\\d{0,2}");
// 获取文本匹配器对象
Matcher m = p.matcher(str);
while(m.find()) {
//知道字符串末尾 find为false
String s=m.group();
System.err.println(s);
}
}
public static void method1(String str) {
// Pattern:表达正则表达式
// Matcher:文本匹配器 作用:按照正则表达式规则读取字符串,从头读取,找到符合规则的子串
// 获取正则表达式对象
Pattern p = Pattern.compile("Java\\d{0,2}");
// 获取文本匹配器对象
// m: 文本匹配器的对象
// str:大串
// p:规则
// 即 m要在str中找到符合p规则的小串
Matcher m = p.matcher(str);
// 拿着文本匹配器从头开始读取,寻找是否有满足规则子串
// 如果有,返回true,并且在底层记录子串的起始索引和结束索引+1
// Java : 0,4
// 如果没有,返回false
boolean flag = m.find();
// 方法底层根据find方法记录的索引进行字符串的截取
// subString(起始索引,结束索引) 包头不包尾
// (0,4) 但是不包含4索引
// 会把截取的小串返回
String s1 = m.group();
System.out.println(s1);
//第二次在调用find的时候,会维续读取后面的内容
//读取到第二个满足要求的子串,方法会继续返回true
//并把第二个子串的起始索引和结束索引+1,进行记录
flag = m.find();
//第二次调用group方法的时候,会根据find方法记录的索引再次截取子串
String s2 = m.group();
System.out.println(s2);
}
}
2.1.1、带条件爬取
public class regexTest {
public static void main(String[] args) {
String str = " Java自从95年问世以来,经历了很多版本,目前企业中用的最多的是"
+ "Java8和JAva11,因为这两个是长期支持版本,下一个长期支持版本是JAVa17,"
+ "相信在未来不久JAVA17也会逐渐登上历史舞台。";
//1.定义正则表达式
//? 表示前面的数据java
// = 表示在java后面要跟随的数据
//但是在获取的时候,只获取后半部分
//需求1:爬取版本号为8,11,17的]ava文本,但是只要]ava,不显示版本号。
String regex = "((?i)Java)(?=8|11|17)";
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(str);
while (m.find()) {
System.out.print(m.group() + ",");
}
System.out.println();
//需求2:爬取版本号为8,11,17的ava文木。正确爬取结果为: Java8 JAva11 JAVa17 JAVA17。
String regex1 = "((?i)Java)(8|11|17)";
Pattern p1 = Pattern.compile(regex1);
Matcher m1 = p1.matcher(str);
while (m1.find()) {
System.out.print(m1.group() + ",");
}
System.out.println();
String regex2 = "((?i)Java)(?:8|11|17)";
Pattern p2 = Pattern.compile(regex2);
Matcher m2 = p2.matcher(str);
while (m2.find()) {
System.out.print(m2.group() + ",");
}
System.out.println();
//需求3:爬取除了版本号为8,11,17的Java文本。
// !去除的意思
String regex3 = "((?i)Java)(?!8|11|17)";
Pattern p3 = Pattern.compile(regex2);
Matcher m3 = p3.matcher(str);
while (m3.find()) {
System.out.print(m3.group() + ",");
}
}
}
2.1.2、贪婪爬取和非贪婪爬取
| 贪婪爬取 | 在爬取数据的时候尽可能多的获取数据库 |
| 非贪婪爬取 | 在爬取数据的时候尽可能少的获取数据库 |
public class regexTest {
public static void main(String[] args) {
//Java当中,默认的就是贪婪爬取
//如果我们在数量词 + * 的后面加上问号 那么就是非贪婪爬取
String str = " Java自从95年问世以来,abbbbbbbbbbbbb" +
"经历了很多版本,目前企业中用的最多的是"
+"Java8和JAva11,因为这两个是长期支持版本,下一个长期支持版本是JAVa17," +
"相信在未来不久JAVA17也会逐渐登上历史舞台。";
//需求1:按照ab+的方式爬取ab,b尽可能多获取
//需求2:按照ab+的方式爬取ab,b尽可能少获取
String regex = "ab+";
Pattern p = Pattern.compile(regex);
Matcher m=p.matcher(str);
while (m.find()) {
System.out.println(m.group());
}
String regex1 = "ab+?";
Pattern p1 = Pattern.compile(regex1);
Matcher m1=p1.matcher(str);
while (m1.find()) {
System.out.println(m1.group());
}
}
}
2.2、网络爬虫(了解)
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class regexTest {
public static void main(String[] args) {
//将某个URL网址中所有的身份证号码提取出来
//创建一个URL对象
URL url = new URL();
//连接上网址
//细节:保证网络是畅通的
URLConnection conn = url.openConnection();
//创建一个对象去读取网路中的数据
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
//获取正则表达式对象
String regex = "[1-9]\\d{17}";
Pattern pattern = Pattern.compile(regex);
//在读取的时候每次读一整行
while((line = br.readLine())!=null) {
System.out.println(line);
//拿着文本匹配器的对象matcher按照pattern的规则去读取当前这一行信息
Matcher m = pattern.matcher(line);
while(m.find()) {
System.out.println(m.group());
}
}
}
}
三、分组
分组就是一个小括号。
每组是有组号的,也就是序号。
规则1:从1开始,连续不间断。
规则2:以左括号为基准,最左边的是第一组,其次为第二组,以此类推。
eg:(\\d+(\\d+))(\\d+);第一组(\\d+(\\d+))第二组(\\d+)第三组(\\d+)
3.1、捕获分组
捕获分组(默认)就是把这一组的数据捕获出来,再用一次。
组号的特点:
从1开始,连续不间断;以左括号为基准,最左边的是第一组。
| 正则内部使用 | \\组号 |
| 正则外部使用 | $组号 |
public class regexTest {
public static void main(String[] args) {
//需求1:判断一个字符串的开始字符和结束字符是否一致?只考虑一个字符
//举例::a123a b456b 17891 &abc&
// \\组号 表示把把x组内容再拿出来用一次
String regex1 = "(.).+\\1";
System.out.println("a123a".matches(regex1)); // true
System.out.println("&abc&".matches(regex1)); // true
System.out.println("b4561".matches(regex1)); // false
//需求2:判断一个字符串的开始部分和结束部分是否一致?可以有多个字符
//举例:abc123abc b456b 123789123 &!@abc&!@
String regex2 = "(.+).+\\1";
System.out.println("abc123abc".matches(regex2)); // true
System.out.println("&!@abc&!@".matches(regex2)); // true
System.out.println("123789b".matches(regex2)); // false
//需求3:判断一个字符串的开始部分和结束部分是否一致?开始部分内部每个字符也需要一致
//举例:aaa123aaa bbb456bbb 111789111 &&abc&&
//某某某需要一致 需要捕获分组
// (.) 把首字母看成一组
// \\2 被首字母拿出来再次使用
// * 作用于\\1 表示后面重复的内容出现0次或者多次
String regex3 = "((.)\\2*).+\\1";
System.out.println("aaa123aaa".matches(regex3)); // true
System.out.println("&&abc&&".matches(regex3)); // true
System.out.println("111789123".matches(regex3)); // false
}
}
public class Main {
public static void main(String[] args) {
/*需求:
将字符串:我要学学编编编编程程程程程
替换为:我要学编程*/
String str = "我要学学编编编编程程程程程";
//需求:把重复的内容 替换为 单个的
//学学 学
//编编编编 编
//程程程程程程 程
//(.) 表示把重复内容的第一个字符看做一组
//\\1 表示第一字符再次出现
//+ 至少一次
//$1 表示把正则表达式中第一组的内容,再拿出来用
String result = str.replaceAll("(.)\\1+", "$1");
System.out.println(result);
}
}
3.2、非捕获分组
分组之后不需要再用本组数据,仅仅把数据括起来,不占组号。
| 符号 | 含义 | 举例 |
| (?:正则) | 获取所有 | Java(?:8|11|17) |
| (? = 正则) | 获取前面部分 | Java(?=8|11|17) |
| (?! 正则) | 获取不是指定内容的前面部分 | Java(?!8|11|17) |
public class regexTest {
public static void main(String[] args) {
//身份证号码的 简易正则表达式
//非捕获分组:仅仅是把数据概括起来
//特点:不占用组号
// (?:) (?=) (?!)
//更多使用第一个
String regex = "[1-9]\\d{16}(?:\\d|x|x)\\1";
String regex1 = "[1-9]\\d{16}(\\d|x|x)\\1";
System.out.println("41080119930228457x".matches(regex));
}
}
4759

被折叠的 条评论
为什么被折叠?



