Java——正则表达式

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));
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值