概述及基本使用
正则表达式:是指用来描述或者匹配一系列符合某个句法规则的字符串的单个字符串。
QQ号判断:
public static boolean checkQQ(String qq) {
// String regex ="[1-9][0-9]{4,14}";
// //public boolean matches(String regex)告知此字符串是否匹配给定的正则表达式
// boolean flag = qq.matches(regex);
// return flag;
//return qq.matches("[1-9][0-9]{4,14}");
return qq.matches("[1-9]\\d{4,14}");
}
正则表达式的组成规则
- 规则字符在
java.util.regex Pattern
类中
常见组成规则
- 通配符
\
: 引用符,用来表示某些特殊字符本身。.
: 匹配除\r\n
之外的任何单个字符。如果要表达.
字符本身,用\.
表示。最终输入的效果为\\.
\b
: 匹配单词边界,即 不是单词字符的地方。
- 举例:hello
space
world?
haha;
- 举例:hello
\B
: 匹配\b
之外的任意字符。\n
:匹配换行符 (‘\u000A’)\r
:匹配回车符 (‘\u000D’)\t
:匹配制表符 (‘\u0009’)</li>
\d
<li>:匹配[0-9]任意一个数字</li>
\D
<li>:匹配非数字与
[^0-9]相同</li>
\w
<li>:匹配包括下划线在内的任意单词字符
[a-zA-Z_0-9]
<ul><li>在正则表达式里面组成单词的东西必须有这些东西组成</li></ul></li>
<li>: 匹配非单词字符:
[^\w]</li>
\s`: 匹配任何不可见字符,包括空格、制表符、换页符等等。
<li>
边界匹配器
^
: 行的开头$
: 行的结尾
字符类
[abc]
: a、b 或 c(简单类)[^abc]
: 任何字符,除了 a、b 或 c(否定)[a-zA-Z]
: a到 z 或 A到 Z,两头的字母包括在内(范围)[x|y]
: 匹配X或y[0-9]
: 0到9的字符都包括
数量词
X?
: X 匹配 零次或一次X*
: X 匹配 零次或多次X+
: X 匹配 一次或多次X{n}
: X 匹配 恰好 n 次X{n,}
: X 匹配 至少 n 次X{n,m}
: X 匹配 至少 n 次 匹配 至多 m 次
非贪婪匹配
- 在满足匹配时,匹配尽可能短的字符串,使用?来表示非贪婪匹配
*?
重复任意次,但尽可能少重复+?
重复1次或更多次,但尽可能少重复??
重复0次或1次,但尽可能少重复{n,m}?
重复n到m次,但尽可能少重复{n,}?
重复n次以上,但尽可能少重复
非获取匹配
(?:pattern)
: 匹配pattern但不获取匹配结果,不进行存储供以后使用。这在使用或字符“(|)”来组合一个模式的各个部分是很有用。例如“industr(?:y|ies)”就是一个比“industry|industries”更简略的表达式。(?=pattern)
: 正向肯定预查,在任何匹配pattern的字符串开始处匹配查找字符串,该匹配不需要获取供以后使用。例如,“Windows(?=95|98|NT|2000)”能匹配“Windows2000”中的“Windows”,但不能匹配“Windows3.1”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。(?!pattern)
: 正向否定预查,在任何不匹配pattern的字符串开始处匹配查找字符串,该匹配不需要获取供以后使用。例如“Windows(?!95|98|NT|2000)”能匹配“Windows3.1”中的“Windows”,但不能匹配“Windows2000”中的“Windows”。(?<=pattern)
: 反向肯定预查,与正向肯定预查类似,只是方向相反。例如,“(?<=95|98|NT|2000)Windows”能匹配“2000Windows”中的“Windows”,但不能匹配“3.1Windows”中的“Windows”。(?<!pattern)
: 反向否定预查,与正向否定预查类似,只是方向相反。例如“(?
正则表达式的应用
判断功能(String
类)
- public boolean
matches
(String regex) - 手机号码练习:
public class PhoneNumber {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Pleas input you phonenumber:");
String phone = sc.nextLine();
String regex = "1[38]\\d{9}";
boolean flag = phone.matches(regex);
System.out.println("The Phone Number is:"+flag);
}
}
- 邮箱验证:
public class RegexTest {
public static void main(String[] args) {
//键盘录入邮箱
Scanner sc = new Scanner(System.in);
System.out.println("请输入邮箱:");
String email = sc.nextLine();
//定义邮箱的规则
//String regex = "[a-zA-Z_0-9]+@[a-zA-Z_0-9]{2,6}(\\.[a-zA-Z_0-9]{2,3})+";
String regex = "\\w+@\\w{2,6}(\\.\\w{2,3})+";
//调用功能,判断即可
boolean flag = email.matches(regex);
//输出结果
System.out.println("flag:"+flag);
}
}
分割功能(String
类)
public String[] split(String regex)
练习1:
public class RegexDemo {
public static void main(String[] args) {
//定义一个年龄搜索范围
String ages = "18-24";
//定义规则
String regex = "-";
//调用方法
String[] strArray = ages.split(regex);
//如何得到int类型的呢?
int startAge = Integer.parseInt(strArray[0]);
int endAge = Integer.parseInt(strArray[1]);
//键盘录入年龄
Scanner sc = new Scanner(System.in);
System.out.println("请输入你的年龄:");
int age = sc.nextInt();
if(age>=startAge && age<=endAge) {
System.out.println("你就是我想找的");
}else {
System.out.println("不符合我的要求,gun");
}
}
}
- 练习2:
public class RegexDemo2 {
public static void main(String[] args) {
// 定义一个字符串
String s1 = "aa,bb,cc";
// 直接分割
String[] str1Array = s1.split(",");
for (int x = 0; x < str1Array.length; x++) {
System.out.println(str1Array[x]);
}
System.out.println("---------------------");
String s2 = "aa.bb.cc";
String[] str2Array = s2.split("\\.");
for (int x = 0; x < str2Array.length; x++) {
System.out.println(str2Array[x]);
}
System.out.println("---------------------");
String s3 = "aa bb cc";
String[] str3Array = s3.split(" +");
for (int x = 0; x < str3Array.length; x++) {
System.out.println(str3Array[x]);
}
System.out.println("---------------------");
//硬盘上的路径,我们应该用\\替代\
String s4 = "E:\\JavaSE\\day14\\avi";
String[] str4Array = s4.split("\\\\");
for (int x = 0; x < str4Array.length; x++) {
System.out.println(str4Array[x]);
}
System.out.println("---------------------");
}
}
- 练习3:
/*
* 我有如下一个字符串:"91 27 46 38 50"
* 请写代码实现最终输出结果是:"27 38 46 50 91"
*
* 分析:
* A:定义一个字符串
* B:把字符串进行分割,得到一个字符串数组
* C:把字符串数组变换成int数组
* D:对int数组排序
* E:把排序后的int数组在组装成一个字符串
* F:输出字符串
*/
public class RegexTest {
public static void main(String[] args) {
// 定义一个字符串
String s = "91 27 46 38 50";
// 把字符串进行分割,得到一个字符串数组
String[] strArray = s.split(" ");
// 把字符串数组变换成int数组
int[] arr = new int[strArray.length];
for (int x = 0; x < arr.length; x++) {
arr[x] = Integer.parseInt(strArray[x]);
}
// 对int数组排序
Arrays.sort(arr);
// 把排序后的int数组在组装成一个字符串
StringBuilder sb = new StringBuilder();
for (int x = 0; x < arr.length; x++) {
sb.append(arr[x]).append(" ");
}
//转化为字符串
String result = sb.toString().trim();
//输出字符串
System.out.println("result:"+result);
}
}
替换功能(String
类)
- public String
replaceAll
(String regex,String replacement)
public class RegexDemo {
public static void main(String[] args) {
// 定义一个字符串
String s = "helloqq12345worldkh622112345678java";
// 我要去除所有的数字,用*给替换掉
// String regex = "\\d+";
// String regex = "\\d";
//String ss = "*";
// 直接把数字干掉
String regex = "\\d+";
String ss = "";
String result = s.replaceAll(regex, ss);
System.out.println(result);
}
}
获取功能(Pattern和Matcher类的使用)
- Pattern和Matcher类的使用
模式和匹配器的基本使用顺序
- step1: 把正则表达式编译成
模式对象
- Pattern p = Pattern.compile(“a*b”);
- step2: 通过模式对象得到匹配器对象,这个时候需要的是被匹配的字符串
- Matcher m = p.matcher(“aaaaab”);
- step3: 调用匹配器对象的功能
- boolean b = m.matches();
- step1: 把正则表达式编译成
find():查找存不存在
- group():获取刚才查找过的数据
public class RegexDemo {
public static void main(String[] args) {
// 模式和匹配器的典型调用顺序
//step1: 把正则表达式编译成模式对象
Pattern p = Pattern.compile("a*b");
//step2: 通过模式对象得到匹配器对象,这个时候需要的是被匹配的字符串
Matcher m = p.matcher("aaaaab");
//step3: 调用匹配器对象的功能
boolean b = m.matches();
System.out.println(b);
//这个是判断功能,但是如果做判断,这样做就有点麻烦了,我们直接用字符串的方法做
String s = "aaaaab";
String regex = "a*b";
boolean bb = s.matches(regex);
System.out.println(bb);
}
}
- 获取下面这个字符串中由三个字符组成的单词
/*
* 获取功能:
* 获取下面这个字符串中由三个字符组成的单词
* da jia ting wo shuo,jin tian yao xia yu,bu shang wan zi xi,gao xing bu?
*/
public class RegexDemo2 {
public static void main(String[] args) {
// 定义字符串
String s = "da jia ting wo shuo,jin tian yao xia yu,bu shang wan zi xi,gao xing bu?";
// 规则
String regex = "\\b\\w{3}\\b";
// 把规则编译成模式对象
Pattern p = Pattern.compile(regex);
// 通过模式对象得到匹配器对象
Matcher m = p.matcher(s);
// 调用匹配器对象的功能
// 通过find方法就是查找有没有满足条件的子串
// public boolean find()
// boolean flag = m.find();
// System.out.println(flag);
// // 如何得到值呢?
// // public String group()
// String ss = m.group();
// System.out.println(ss);
while (m.find()) {
System.out.println(m.group());
}
// 注意:一定要先find(),然后才能group()
// IllegalStateException: No match found
// String ss = m.group();
// System.out.println(ss);
}
}
常用正则表达式整理
校验数字的表达式
- 数字:
^[0-9]*$
- n位的数字:
^\d{n}$
- 至少n位的数字:
^\d{n,}$
- m-n位的数字:
^\d{m,n}$
- 零和非零开头的数字:
^(0|[1-9][0-9]*)$
- 非零开头的最多带两位小数的数字:
^([1-9][0-9]*)+(\.[0-9]{1,2})?$
- 带1-2位小数的正数或负数:
^(\-)?\d+(\.\d{1,2})?$
- 正数、负数、和小数:
^(\-|\+)?\d+(\.\d+)?$
- 有两位小数的正实数:
^[0-9]+(\.[0-9]{2})?$
- 有1~3位小数的正实数:
^[0-9]+(\.[0-9]{1,3})?$
- 非零的正整数:
^[1-9]\d*$
- 非零的负整数:
^-[1-9]\d*$
- 非负整数:
^\d+$
或^[1-9]\d*|0$
- 非正整数:
^-[1-9]\d*|0$
或^((-\d+)|(0+))$
- 浮点数:
^(-?\d+)(\.\d+)?$
或^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$
校验字符的表达式
- 汉字:
^[\u4e00-\u9fa5]{0,}$
- 英文和数字:
^[A-Za-z0-9]+$
- 长度为3-20的所有字符:
^.{3,20}$
- 由26个英文字母组成的字符串:
^[A-Za-z]+$
- 由26个大写英文字母组成的字符串:
^[A-Z]+$
- 由26个小写英文字母组成的字符串:
^[a-z]+$
- 由数字和26个英文字母组成的字符串:
^[A-Za-z0-9]+$
- 由数字、26个英文字母或者下划线组成的字符串:
^\w+$
- 中文、英文、数字包括下划线:
^[\u4E00-\u9FA5A-Za-z0-9_]+$
- 中文、英文、数字但不包括下划线等符号:
^[\u4E00-\u9FA5A-Za-z0-9]+$
- 可以输入含有
^%&’,;=?$\"
等字符:[^%&',;=?$\x22]+
- 禁止输入含有
~
的字符:[^~\x22]+
特殊需求表达式
- 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})+/.?
- InternetURL:
[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}
- 身份证号(15位、18位数字):
^\d{15}|\d{18}$
- 短身份证号码(数字、字母x结尾):
^([0-9]){7,18}(x|X)?$
或^\d{8,18}|[0-9x]{8,18}|[0-9X]{8,18}?$
- 帐号是否合法(字母开头,允许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]).{8,10}$
.*
用于实际匹配字符串,即匹配任意字符串到尾部
- 腾讯QQ号:
[1-9][0-9]{4,}
(腾讯QQ号从10000开始) - 中国邮政编码:
[1-9]\d{5}(?!\d)
(中国邮政编码为6位数字) - IP地址:
\d+\.\d+\.\d+\.\d+
(提取IP地址时有用) - IP地址:
((?:(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d))
运算符优先级
正则表达式从左到右进行计算,并遵循优先级顺序,这与算术表达式非常类似。
相同优先级的从左到右进行运算,不同优先级的运算先高后低。下表从最高到最低说明了各种正则表达式运算符的优先级顺序:
运算符 | 描述 |
---|---|
\ | 转义符 |
(), (?:), (?=), [] | 圆括号和方括号 |
*, +, ?, {n}, {n,}, {n,m} | 限定符 |
^, $, \任何元字符、任何字符 | 定位点和序列(即:位置和顺序) |
* |
: 替换”或”操作 字符具有高于替换运算符的优先级,使得 m|food
匹配”m”或”food”。若要匹配”mood”或”food”,请使用括号创建子表达式,从而产生(m|food)
。