Java学习笔记(正则表达式)

tech2026-06-07  3

知识点总结于毕向东Java基础视频教程25天版本,侵权请联系删除。

正则表达式

正则表达式概述规则字符字符类预定义字符类POSIX 字符类(仅 US-ASCII)边界匹配器Greedy 数量词Logical 运算符常用规则 匹配切割分组 替换获取Pattern类和Matcher类 网页爬虫获取邮箱

正则表达式

概述

正则表达式,又称规则表达式。(英语:Regular Expression,在代码中常简写为regex、regexp或RE),计算机科学的一个概念。正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本。在众多语言中都可以支持正则表达式,如Perl、PHP、Java、Python、Ruby等。 当然在Java中也可以通过处理字符串的方式达到检索,替换文本字符串的目的,但是有了正则表达式写代码更加简洁,通常两三行代码就可以达到目的,当然这也是建立在熟悉正则表达式的基础之上的。

作用:用于专门操作字符串。特点:用一些特定的符号来表示一些代码操作,这样就简化了书写。所以学习正则表达式,就是在学习一些特殊符号的使用。好处:可以简化对字符串的复杂操作。弊端:符号定义越多,正则越长,阅读性越差。

规则

字符

字符说明x字符 x\反斜线字符\0n带有八进制值 0 的字符 n (0 <= n <= 7)\0nn带有八进制值 0 的字符 nn (0 <= n <= 7)\0mnn带有八进制值 0 的字符 mnn(0 <= m <= 3、0 <= n <= 7)\xhh带有十六进制值 0x 的字符 hh\uhhhh带有十六进制值 0x 的字符 hhhh\t制表符 (’\u0009’)\n新行(换行)符 (’\u000A’)\r回车符 (’\u000D’)\f换页符 (’\u000C’)\a报警 (bell) 符 (’\u0007’)\e转义符 (’\u001B’)\cx对应于 x 的控制符

字符类

字符类说明[abc]a、b 或 c(简单类)[^abc]任何字符,除了 a、b 或 c(否定)[a-zA-Z]a 到 z 或 A 到 Z,两头的字母包括在内(范围)[a-d[m-p]]a 到 d 或 m 到 p:[a-dm-p](并集)[a-z&&[def]]d、e 或 f(交集)[a-z&&[^bc]]a 到 z,除了 b 和 c:[ad-z](减去)[a-z&&[^m-p]]a 到 z,而非 m 到 p:[a-lq-z](减去)

预定义字符类

预定义字符类说明.任何字符(与行结束符可能匹配也可能不匹配)\d数字:[0-9]\D非数字: [^0-9]\s空白字符:[ \t\n\x0B\f\r]\S非空白字符:[^\s]\w单词字符:[a-zA-Z_0-9]\W非单词字符:[^\w]

POSIX 字符类(仅 US-ASCII)

POSIX 字符类说明\p{Lower}小写字母字符:[a-z]\p{Upper}大写字母字符:[A-Z]\p{ASCII}所有 ASCII:[\x00-\x7F]\p{Alpha}字母字符:[\p{Lower}\p{Upper}]\p{Digit}十进制数字:[0-9]\p{Alnum}字母数字字符:[\p{Alpha}\p{Digit}]\p{Punct}标点符号:!"#$%&’()*+,-./:;<=>?@[]^_`{\p{Graph}可见字符:[\p{Alnum}\p{Punct}]\p{Print}可打印字符:[\p{Graph}\x20]\p{Blank}空格或制表符:[ \t]\p{Cntrl}控制字符:[\x00-\x1F\x7F]\p{XDigit}十六进制数字:[0-9a-fA-F]\p{Space}空白字符:[ \t\n\x0B\f\r]

边界匹配器

边界匹配器说明^行的开头$行的结尾\b单词边界\B非单词边界\A输入的开头\G上一个匹配的结尾\Z输入的结尾,仅用于最后的结束符(如果有的话)\z输入的结尾

Greedy 数量词

Greedy 数量词说明X?X出现一次或一次也没有X*X出现零次或多次X+X出现一次或多次X{n}X恰好出现 n 次X{n,}X至少出现 n 次X{n,m}X至少出现 n 次,但是不超过 m 次

Logical 运算符

Logical 运算符说明XYX 后跟 YXY(X)X,作为捕获组

常用规则

任意一个字符表示匹配任意对应的字符,如a匹配a,7匹配7,-匹配-。

[]代表匹配中括号中其中任一个字符,如[abc]匹配a或b或c。

-在中括号里面和外面代表含义不同,如在外时,就匹配-,如果在中括号内[a-b]表示匹配26个小写字母中的任一个;[a-zA-Z]匹配大小写共52个字母中任一个;[0-9]匹配十个数字中任一个。

^在中括号里面和外面含义不同,如在外时,就表示开头, 如^7[0-9]表示匹配开头是7的,且第二位是任一数字的字符串;如果在中括号里面,表示除了这个字符之外的任意字符(包括数字,特殊字符),如[^abc]表示匹配出去abc之外的其他任一字符。

.表示匹配任意的字符。

\d表示数字。

\D表示非数字。

\s表示由空字符组成,[ \t\n\r\x\f]。

\S表示由非空字符组成,[^\s]。

\w表示字母、数字、下划线,[a-zA-Z0-9_]。

\W表示不是由字母、数字、下划线组成。

?: 表示出现0次或1次。

+表示出现1次或多次。

*表示出现0次、1次或多次。

{n}表示出现n次。

{n,m}表示出现n~m次。

{n,}表示出现n次或n次以上。

XY表示X后面跟着Y,这里X和Y分别是正则表达式的一部分。

X|Y表示X或Y,比如"food|f"匹配的是foo(d或f),而"(food)|f"匹配的是food或f。

(X)子表达式,将X看做是一个整体。

作者:Vic_is_new_Here 链接:https://www.jianshu.com/p/3c076c6b2dc8

匹配

String matches方法。用规则匹配整个字符串,只要有一处不符合规则,就匹配结束,返回false。

class Demo { public static void main(String[] args){ String str="01231231"; String str1="111111111111111";//15个1 String regex="[1-9]\\d{4,14}"; //代表第一个字符为数字,除去第一个字符后的所有字符都为数字且最多有14个 System.out.println(str.matches(regex));//false System.out.println(str1.matches(regex));//true } }

切割

String split(String regex);

class Demo { public static void main(String[] args){ String str="D:\\Demo\\Demo.txt"; //一个\为转义字符,需要再加一个转义字符将后面的\转义为字符形式的\,所以两个字符形式的\\就是各需要一个转义字符将其转义 String regex="\\\\"; splitDemo(str,regex); //在正则表达式中.代表任何字符,所以在正则表达式中需要转义字符将其转义即'\.',但是在字符串中'\.'将'.'转义没有意义,所以需要再加一个转义字符将'\.'转译为在字符串中的两个普通字符 splitDemo("1.2.3.4","\\."); //按照叠词完成切割。 //可以将规则封装成一个组。用()完成。组的出现都有编号。 //从1开始。 想要使用已有的组可以通过 \n(n就是组的编号)的形式来获取。 splitDemo("aadnsasssmxksddddasm","(.)\\1+"); } public static void splitDemo(String str,String regex){ String[] arr = str.split(regex); System.out.println(arr.length); for(String s : arr) { System.out.println(s); } System.out.println("---------"); } }

分组

我们可以通过括号将多个字符组合为一个单位。例如(ab)。

正则表达式中的每个组都有一个组号,从1开始。

Matcher类中的方法groupCount()返回与Matcher实例相关联的模式中的组数。

组0引用整个正则表达式和不由groupCount()方法报告。

正则表达式中的每个左括号标记新组的开始。

我们可以在正则表达式中返回引用组号。

假设我们要匹配以“abc"开头,后跟“xyz"的文本,后跟“abc"。

我们可以写一个正则表达式为“abcxyzabc"。

我们可以使用反向引用将正则表达式重写为“(abc)xyz \ 1"。

\1 指第1组,即(abc),\2 引用组2, \3 引用组3,依此类推。

替换

replaceAll(String regex, String replacement); 使用给定的参数 replacement 替换字符串所有匹配给定的正则表达式的子字符串。

如果regex中有定义组,可以在第二参数中通过$符号获取正则表达式中的已有的组。

class Demo { public static void main(String[] args){ String str="dsak1151351dsa213dsad546846"; replaceAllDemo(str,"\\d{5,}","*"); //将字符串中数字连续超过5个(包括5)的替换成* String str1="qqqnxsjkawwwnxszzsjk"; replaceAllDemo(str1,"(.)\\1+","$1");//将字符串中的叠词替换成1个叠词的字符 } public static void replaceAllDemo(String str,String reg,String sign) { str = str.replaceAll(reg,sign); System.out.println(str); } }

获取

Pattern类和Matcher类

结论:Pattern与Matcher一起合作,Matcher类提供了对正则表达式的分组支持,以及对正则表达式的多次匹配支持。 单独用Pattern只能使用Pattern.matcher(String regex,CharSequence input)一种最基础最简单的匹配。

Pattern类用于创建一个正则表达式,也可以说创建一个匹配模式,它的构造方法是私有的,不可以直接创建,但可以通过Pattern.complie(String regex)简单工厂方法创建一个正则表达式。 Pattern p=Pattern.compile("\w+"); p.pattern();//返回 \w+ //pattern() 返回正则表达式的字符串形式,其实就是返回Pattern.complile(String regex)的regex参数

常用方法: 1.Pattern.split(CharSequence input) Pattern有一个split(CharSequence input)方法,用于分隔字符串,并返回一个String[],String.split(String regex)就是通过Pattern.split(CharSequence input)来实现的. Java代码示例: //讲指定的正则表达式加载进Pattern类 Pattern p=Pattern.compile("\\d+"); String[] str=p.split("我的QQ是:456456我的电话是:0532214我的邮箱是:aaa@aaa.com"); 结果:str[0]="我的QQ是:" str[1]="我的电话是:" str[2]="我的邮箱是:aaa@aaa.com" 2.Pattern.matches(String regex,CharSequence input)是一个静态方法,用于快速匹配字符串,该方法适合用于只匹配一次,且匹配全部字符串. Java代码示例: Pattern.matches("\\d+","2223");//返回true Pattern.matches("\\d+","2223aa");//返回false,需要匹配到所有字符串才能返回true,这里aa不能匹配到 Pattern.matches("\\d+","22bb23");//返回false,需要匹配到所有字符串才能返回true,这里bb不能匹配到 3.Pattern.matcher(CharSequence input):Pattern.matcher(CharSequence input)返回一个Matcher对象. Matcher类的构造方法也是私有的,不能随意创建,只能通过Pattern.matcher(CharSequence input)方法得到该类的实例. Pattern类只能做一些简单的匹配操作,要想得到更强更便捷的正则匹配操作,那就需要将Pattern与Matcher一起合作.Matcher类提供了对正则表达式的分组支持,以及对正则表达式的多次匹配支持. Pattern p=Pattern.compile("\d+"); Matcher m=p.matcher(“22bb23”); m.pattern();//返回p 也就是返回该Matcher对象是由哪个Pattern对象的创建的 //将字符串中的符合规则的子串取出。

1.Matcher.matches()/ Matcher.lookingAt()/ Matcher.find() Matcher类提供三个匹配操作方法,三个方法均返回boolean类型,当匹配到时返回true,没匹配到则返回false matches()对整个字符串进行匹配,只有整个字符串都匹配了才返回true Java代码示例: Pattern p=Pattern.compile("\\d+"); Matcher m=p.matcher("22bb23"); m.matches();//返回false,因为bb不能被\d+匹配,导致整个字符串匹配未成功. Matcher m2=p.matcher("2223"); m2.matches();//返回true,因为\d+匹配到了整个字符串 我们现在回头看一下Pattern.matches(String regex,CharSequence input),它与下面这段代码等价 Pattern.compile(regex).matcher(input).matches() lookingAt()对前面的字符串进行匹配,只有匹配到的字符串在最前面才返回true Java代码示例: Pattern p=Pattern.compile("\\d+"); Matcher m=p.matcher("22bb23"); m.lookingAt();//返回true,因为\d+匹配到了前面的22 Matcher m2=p.matcher("aa2223"); m2.lookingAt();//返回false,因为\d+不能匹配前面的aa find()对字符串进行匹配,匹配到的字符串可以在任何位置. Java代码示例: Pattern p=Pattern.compile("\\d+"); Matcher m=p.matcher("22bb23"); m.find();//返回true Matcher m2=p.matcher("aa2223"); m2.find();//返回true Matcher m3=p.matcher("aa2223bb"); m3.find();//返回true Matcher m4=p.matcher("aabb"); m4.find();//返回false 2.Mathcer.start()/ Matcher.end()/ Matcher.group() 当使用matches(),lookingAt(),find()执行匹配操作后,就可以利用以上三个方法得到更详细的信息. start()返回匹配到的子字符串在字符串中的索引位置. end()返回匹配到的子字符串的最后一个字符在字符串中的索引位置. group()返回匹配到的子字符串 Java代码示例: Pattern p=Pattern.compile("\\d+"); Matcher m=p.matcher("aaa2223bb"); m.find();//匹配2223 m.start();//返回3 m.end();//返回7,返回的是2223后的索引号 m.group();//返回2223 Mathcer m2=p.matcher("2223bb"); m2.lookingAt(); //匹配2223 m2.start(); //返回0,由于lookingAt()只能匹配前面的字符串,所以当使用lookingAt()匹配时,start()方法总是返回0 m2.end(); //返回4 m2.group(); //返回2223 Matcher m3=p.matcher("2223"); //如果Matcher m3=p.matcher("2223bb"); 那么下面的方法出错,因为不匹配返回false m3.matches(); //匹配整个字符串 m3.start(); //返回0 m3.end(); //返回3,原因相信大家也清楚了,因为matches()需要匹配所有字符串 m3.group(); //返回2223

操作步骤:

将正则表达式封装成对象。让正则对象和要操作的字符串相关联。关联后,获取正则匹配引擎。通过引擎对符合规则的子串进行操作,比如取出。 import java.util.regex.*; class Demo { public static void main(String[] args){ String str="zheng ze biao da shi"; String regex="\\b[a-z]{2,}\\b"; // \b在正则表达式中为单词边界 Pattern p= Pattern.compile(regex); Matcher m=p.matcher(str); //m.matches(); //匹配整个字符串,调用该方法后索引位置会发生改变,可能会导致匹配字符的遗漏 //类似于迭代器,先查找字符串中是否有匹配的数据,如果有就获取 while(m.find()){ System.out.println(m.group()); } } }

网页爬虫

网络爬虫(又称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。另外一些不常使用的名字还有蚂蚁、自动索引、模拟程序或者蠕虫。

获取邮箱

import java.util.*; import java.util.regex.*; import java.net.*; import java.io.*; class Demo { public static void main(String[] args)throws Exception{ //随便找了一个留邮箱的网页 URL url=new URL("https://www.douban.com/group/topic/14689449/"); URLConnection conn=url.openConnection(); BufferedReader buffin=new BufferedReader(new InputStreamReader(conn.getInputStream())); //@作为分隔符,前面的只要是数字字母下划线'_',后面的只要是数字字母,'.'加上字母出现一次或多次就能匹配 String regex="\\w+@[a-zA-z0-9]+(\\.[a-zA-z]+)+"; Pattern p=Pattern.compile(regex); Matcher m=null; String line=null; while((line=buffin.readLine())!=null){ m=p.matcher(line); while(m.find()){ System.out.println(m.group()); } } } }

(部分)

最新回复(0)