Java知识点–正则表达式
正则表达式是一个强大的字符串处理工具,可以对字符串进行查找,提取,分割,替换等操作。String类里也提供了如下几个特殊的方法。
1.boolean matches(String regex);
2.String replaceAll(String regex,String replacement);
3.String replaceFirst(String regix,String replacement);
String[] split(String regex);
- 合法字符
字符 | 解释 |
---|---|
x | 字符x(x可以代表任何合法字符) |
\0mnn | 8进制数0mnn所表示的字符 |
\xhh | 十六进制值0xhh所表示的字符 |
\uhhhh | 十六进制值0xhhhh所表示的Unicode字符 |
\t | 制表符(‘\u0009’) |
\n | 换行符(‘\u000A’) |
\r | 回车符(‘\u000D’) |
\f | 换页符(‘\u000D’) |
\a | 报警符(‘\u0007’) |
\e | Escape符(‘\u001B’) |
\cx | x对应的控制符。例如,\cM 匹配 CTRL-M。x的值必须为A-Z或a-z之一 |
- 特殊字符
特殊字符 | 解释 |
---|---|
$ | 要匹配一行的结尾。要匹配$字符本身,请使用\$ |
^ | 匹配一行的开头。要匹配^本身,请使用\^ |
() | 标记子表达式的开始和结束的位置,要匹配这些字符请使用 \( 或者 \) |
[] | 用于确定中括号表达式的开始和结束位置。要匹配这些字符,请使用 \[ 或者 \] |
{} | 用于标记前面子表达式中的出现频度。要匹配这些字符,请使用 \{ 或者 \} |
* | 指定前面子表达式可以出现零次或多次。要匹配*本身,请使用 \* |
+ | 指定前面的字符串可以出现一次或多次。要匹配+本身,请使用 \+ |
? | 指定前面的字符串可以出现零次或多次。要匹配?本身,请使用 \? |
. | 匹配除换行符 n之外的任何单字符。要匹配 . 本身,请使用 \. |
\ | 用于转义下一个字符,或指定八进制,十六进制字符。如果须匹配\ ,请用\\ |
` | ` |
- 例子
"\u0041\\\\" //匹配 A\
"\u0061\t" //匹配 a<制表符>
"\\?\\[" // 匹配 ?[
- 预定义字符
预定义字符 | 解释 |
---|---|
. | 可以匹配任何字符 |
\d | 可以匹配0-9的数字 |
\D | 匹配非数字 |
\s | 匹配所有的空白字符,包括空格,制表符,回车符,换页符,换行符等 |
\S | 匹配所有的非空白符 |
\w | 匹配所有的单词字符,包括0-9所有的数字,26个英文字母和下划线(_) |
\W | 匹配所有的非单词字符 |
- 例子
c\\wt //匹配cat,cbt,cct,c0t,c9t等一批字符串
\\d\\d\\\d-\\d\\d\\d-\\d\\d\\d\\d //匹配如000-000-0000形式的电话号码
- 方括号表达式
方括号表达式 | 解释 |
---|---|
表示枚举 | 例如[abc],表示a,b,c其中的任意一个字符:[gz],表示g,z其中任意一个字符 |
表示范围 | 例如[a-f]表示a-f范围内的任意字符:[],表示十六进制字符到范围的字符,范围可以和枚举结合使用,如[a-cx-z]范围内的任意字符 |
表示求否^ | 例如[^ abc],表示非a,b,c的任意字符:[^ a-f],表示不是a-f范围内的任意字符 |
表示与运算&& | 例如[a-z&&[def]],求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] |
表示并运算 | 并运算与前面的枚举类似。例如[a-d[m-p]],表示[a-dm-p] |
- 关于访问符
"((public)|(protected)|(private))" //表示Java三个访问权限之一
- 边界通配符
边界通配符 | 解释 |
---|---|
^ | 行的开头 |
$ | 行的结尾 |
\b | 单词的边界 |
\B | 非单词的边界 |
\A | 输入的开头 |
\G | 前一个匹配的结尾 |
\Z | 输入的结尾,仅用于最后的结束符 |
\z | 输入的结尾 |
- 三种模式的数量表示符
贪婪模式(Greedy) | 勉强模式(Reluctant) | 占用模式(Possessive) | 解释 |
---|---|---|---|
X? | X?? | X?+ | X表达式出现零次或一次 |
X* | X*? | X*+ | X表达式出现零次或多次 |
X+ | X+? | X++ | X表达式出现一次或多次 |
X{n} | X{n}? | X{n}+ | X表达式出现n次 |
X{n,} | X{n,}? | X{n,}+ | X表达式至少出现次 |
X{n,m} | X{n,m}? | X{n,m}+ | X表达式至少出现n次,最多出现m次 |
- 贪婪和勉强模式的对比
public class test01 {
public static void main(String[] args) {
String str="hello java";
//贪婪模式的正则表达式
System.out.println(str.replaceFirst("\\w*", "■"));//输出■ java
//勉强模式的正则表达式
System.out.println(str.replaceFirst("\\w*?", "■"));//输出 ■hello java
}
}
- 使用正则表达式
import java.util.regex.Pattern;
import java.util.regex.Pattern;
public class test02 {
public static void main(String[] args) {
Pattern p=Pattern.compile("a*b");
Matcher matcher = p.matcher("aaaaaaab");
boolean b = matcher.matches();
System.out.println(b);//输出true
}
}
- 提示
Pattern,Pattern同样实现了CharSequence接口
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class test03 {
public static void main(String[] args) {
String str="我喜欢玩炉石传说,加好友对战+123456789"+
"我还玩LOL,但是我很菜,一起开黑+444555666"+
"一起学习Java吗,+447755113";
Matcher m=Pattern.compile("((12\\d)|(44\\d))\\d{6}").matcher(str);
while(m.find()) {
System.out.println(m.group());
}
}
}
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class test04 {
public static void main(String[] args) {
String str="Java is a good programing language!";
Matcher matcher = Pattern.compile("\\w+").matcher(str);
while(matcher.find()) {
System.out.println(matcher.group()+"开始:"+matcher.start()+"结束"+matcher.end());
}
/**
* Java开始:0结束4
* is开始:5结束7
* a开始:8结束9
* good开始:10结束14
* programing开始:15结束25
* language开始:26结束34
*/
}
}
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class test05 {
public static void main(String[] args) {
String[] mails=
{
"shuaige@163.com",
"meinv@qq.com",
"aixi@LOL.org",
"heihei@hh.xx"
};
String mailRegEx="\\w{3,20}@\\w+\\.(com|org|cn|net|gov)";
Pattern pattern = Pattern.compile(mailRegEx);
Matcher matcher=null;
for(String mail:mails) {
if(matcher==null) {
matcher=pattern.matcher(mail);
}else {
matcher.reset(mail);
}
String result=mail+(matcher.matches()?"是":"不是")+"一个有效的地址";
System.out.println(result);
}
}
/*
shuaige@163.com是一个有效的地址
meinv@qq.com是一个有效的地址
aixi@LOL.org是一个有效的地址
heihei@hh.xx不是一个有效的地址
*/
}
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class test06 {
public static void main(String[] args) {
String []message= {
"This document is divided into two sections:",
"Java SE",
"The Java Platform, Standard Edition (Java SE) APIs define the core Java platform for general-purpose computing. These APIs are in modules whose names start with java.",
"JDK",
"The Java Development Kit (JDK) APIs are specific to the JDK and will not necessarily be available in all implementations of the Java SE Platform. These APIs are in modules whose names start with jdk."
};
Pattern pattern = Pattern.compile("Ja\\w*");
Matcher matcher=null;
for(int i=0;i<message.length;i++) {
if(matcher==null) {
matcher=pattern.matcher(message[i]);
}else {
matcher.reset(message[i]);
}
System.out.println(matcher.replaceAll("~~"));
}
}
}
import java.util.Arrays;
public class test07 {
public static void main(String[] args) {
String []message= {
"This document is divided into two sections:",
"Java SE",
"The Java Platform, Standard Edition (Java SE) APIs define the core Java platform for general-purpose computing. These APIs are in modules whose names start with java.",
"JDK",
"The Java Development Kit (JDK) APIs are specific to the JDK and will not necessarily be available in all implementations of the Java SE Platform. These APIs are in modules whose names start with jdk."
};
for(String str:message) {
System.out.println(str.replaceFirst("Ja\\w*", "~~"));
System.out.println(Arrays.toString(str.split(" ")));
}
}
}
到这里,Java的正则表达式及用法基本讲完了,但是正则表达式的强大能力却不止于此,包括之后的爬虫之类的都要用到。
- 常用表达式
Email:
^\w+([-+.]\w+)\*@\w+([-.]\w+)\*\.\w+([-.]\w+)\*$
域名:
[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(/.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+/.?
internet URL:
[a-zA-z]+://[^\s]\* 或 ^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]\*)?$
手机号码:
^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$
国内电话号码(0511-4405222、021-87888822):
\d{3}-\d{8}|\d{4}-\d{7}
电话号码正则表达式(支持手机号码,3-4位区号,7-8位直播号码,1-4位分机号):
((\d{11})|^((\d{7,8})|(\d{4}|\d{3})-(\d{7,8})|(\d{4}|\d{3})-(\d{7,8})-(\d{4}|\d{3}|\d{2}|\d{1})|(\d{7,8})-(\d{4}|\d{3}|\d{2}|\d{1}))$)
身份证号(15位、18位数字),最后一位是校验位,可能为数字或字符X:
(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)
帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):
^[a-zA-Z][a-zA-Z0-9_]{4,15}$
密码(以字母开头,长度在6~18之间,只能包含字母、数字和下划线):
^[a-zA-Z]\w{5,17}$
强密码(必须包含大小写字母和数字的组合,不能使用特殊字符,长度在 8-10 之间):
^(?=.\*\d)(?=.\*[a-z])(?=.\*[A-Z])[a-zA-Z0-9]{8,10}$
强密码(必须包含大小写字母和数字的组合,可以使用特殊字符,长度在8-10之间):
^(?=.\*\d)(?=.\*[a-z])(?=.\*[A-Z]).{8,10}$
日期格式:
^\d{4}-\d{1,2}-\d{1,2}
一年的12个月(01~09和1~12):
^(0?[1-9]|1[0-2])$
一个月的31天(01~09和1~31):
^((0?[1-9])|((1|2)[0-9])|30|31)$
xml文件:
^([a-zA-Z]+-?)+[a-zA-Z0-9]+\\.[x|X][m|M][l|L]$
中文字符的正则表达式:
[\u4e00-\u9fa5]
空白行的正则表达式(可以用来删除空白行):
\n\s\*\r
HTML标记的正则表达式:
<(\S\*?)[^>]\*>.\*?|<.\*? /> ( 首尾空白字符的正则表达式:^\s\*|\s\*$或(^\s\*)|(\s\*$) (可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式)
腾讯QQ号(腾讯QQ号从10000开始):
[1-9][0-9]{4,}
中国邮政编码 (中国邮政编码为6位数字):
[1-9]\d{5}(?!\d)
IP地址:
((?:(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d))