JAVA基础(常用API) —— 正则表达式

 经过之前对于API的学习:JAVA基础 —— API

接下来的文章让我们来了解一下不同类下的方法,但是这些方法不要去背。

而是要去记一下类名和类作用,也可以在以后去查阅API帮助文档。

Math、System、Runtime和Object JAVA基础 (常用API)—— Math、System、Runtime和Object

BigInteger和BigDecimal

JAVa基础(常用API) —— BigInteger和BigDecimal
正则表达式 JAVA基础(常用API) —— 正则表达式
时间相关类 JAVA基础(常用API) —— 时间相关类
包装类 JAVA基础(常用API) —— 包装类

目录

 一、 校验字符串

1.  字符类

2.  预定义字符

3.  数量词

4.  练习

二、  爬虫

1. 本地爬虫

1.1 带条件爬取

1.2  贪婪爬取和非贪婪爬取

2. 网络爬虫

三、分组

 1. 捕获分组

2. 非捕获分组


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.  字符类

字符类(只匹配一个字符):

JAVA基础(常用API) —— 正则表达式_第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
	}
}

2.  预定义字符

 预定义字符(只匹配一个字符):

JAVA基础(常用API) —— 正则表达式_第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
		// 以上正则表达式只能校验单个字符
	}
}

3.  数量词

JAVA基础(常用API) —— 正则表达式_第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
	}
}

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("[email protected]".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
	}
}

二、  爬虫

在一段文字中查找满足要求的内容。

1. 本地爬虫

通过一个小练习来了解什么是本地爬虫:

有如下文本,请按照要求爬取数据。
             Java自从95年问世以来,经历了很多版本,目前企业中用的最多的是Java8和Java11,因为这两个是长期支持版本,下一个长期支持版本是Java17,相信在未来不久Java17也会逐渐登上历史舞台。


要求:找出里面所有的JavaXX

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也会逐渐登上历史舞台。";

		// 获取正则表达式对象
		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);
	}
}

 爬取小规则:

1.1 带条件爬取

需求1:爬取版本号为8,11,17的]ava文本,但是只要]ava,不显示版本号。
需求2:爬取版本号为8,11,17的ava文木。正确爬取结果为: Java8 JAva11 JAVa17 JAVA17。

需求3:爬取除了版本号为8,11,17的Java文本。

public class regexTest {
	public static void main(String[] args) {
		String str = " Java自从95年问世以来,经历了很多版本,目前企业中用的最多的是"
		          + "Java8和JAva11,因为这两个是长期支持版本,下一个长期支持版本是JAVa17,"
						+ "相信在未来不久JAVA17也会逐渐登上历史舞台。";
		
		//1.定义正则表达式
		//? 表示前面的数据java
		// = 表示在java后面要跟随的数据
		//但是在获取的时候,只获取后半部分 
		//需求1
		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
		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
		// !去除的意思
		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() + ",");
		}
		
	}
}

1.2  贪婪爬取和非贪婪爬取

贪婪爬取 在爬取数据的时候尽可能的获取数据库
非贪婪爬取 在爬取数据的时候尽可能的获取数据库

需求1:按照ab+的方式爬取ab,b尽可能多获取

需求2:按照ab+的方式爬取ab,b尽可能少获取

public class regexTest {
	public static void main(String[] args) {
		
		//Java当中,默认的就是贪婪爬取
		//如果我们在数量词 + * 的后面加上问号 那么就是非贪婪爬取
		
		String str = " Java自从95年问世以来,abbbbbbbbbbbbb" + 
	           "经历了很多版本,目前企业中用的最多的是"
				+"Java8和JAva11,因为这两个是长期支持版本,下一个长期支持版本是JAVa17," + 
	           "相信在未来不久JAVA17也会逐渐登上历史舞台。";
		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. 网络爬虫

通过下面代码来了解什么是网络爬虫:

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());
			}
		}
		
	}
}

三、分组

分组就是一个小括号。 

JAVA基础(常用API) —— 正则表达式_第4张图片

 每组是有组号的,也就是序号。

规则1:从1开始,连续不间断。

规则2:以左括号为基准,最左边的是第一组,其次为第二组,以此类推。

 1. 捕获分组

捕获分组(默认)就是把这一组的数据捕获出来,再用一次。

组号的特点:

从1开始,连续不间断;以左括号为基准,最左边的是第一组。

正则内部使用 \\组号
正则外部使用 $组号

需求1:判断一个字符串的开始字符和结束字符是否一致?只考虑一个字符
举例::a123a b456b 17891 &abc&

需求2:判断一个字符串的开始部分和结束部分是否一致?可以有多个字符

举例:abc123abc  b456b  123789123  &!@abc&!@

需求3:判断一个字符串的开始部分和结束部分是否一致?开始部分内部每个字符也需要一致
举例:aaa123aaa  bbb456bbb  111789111  &&abc&&

public class regexTest {
	public static void main(String[] args) {
		// 需求1
		// \\组号 表示把把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
		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
		//某某某需要一致 需要捕获分组
		// (.) 把首字母看成一组
		//  \\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
	}
}

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));
	}
}

你可能感兴趣的:(JAVA基础入门,正则表达式,java)