正则表达式
正则表达式是一个应用广泛的程序类库。在项目开发中,String是一个重要的程序 类,String除了可以实现数据的接受、各类数据类型的转型外,其本身也支持正则表达式(Regular Expression),利用正则表达式可以方便地实现疏忽的拆分、替换、验证的操作。
正则表达式最早是从UINX系统的工具组件中发展而来的,在JDK 1.4以前如果需要使用到正则表达式的相关定义则需单独引入其他的.jar文件,而从JDK 1.4后,正则已经默认被JDK所支持,并且提供有java.util.regex开发包。与此同时,也针对了String类进行了一定修改,使其有方法直接支持正则处理。
范例1:正则表达式初体验
package edu.zhku.test;
public class RegularExpressionTestDemo01 {
public static void main(String[] args) {
//字符串对象
String string = "123";
//结构匹配("\\d+":判断是否为多为数字)
if (string.matches("\\d+")) {
//字符串转换为int类型
int num = Integer.parseInt(string);
System.out.println(num);
//数字计算
System.out.println(num * 2);
}
}
}
/*
输出结果:
123
246
*/
本程序主要功能是判断字符串的组成是否全部为数字,在本程序中通过一个给定的正则标记"\\d+"(判断是否为多为数字)并结合String类提供的mathes()方法实现验证匹配,如果匹配成功则将字符串转为int型进行计算。
1、常用正则标记
正则表达式中的核心操作是围绕着正则标记的定义实现的。在正则表达式的处理中,最为重要的就是正则匹配标记的使用,所有的正则标记都在java.util.regex.Pattern类中定义,下面列举一些常用的正则标记。
1、元字符:匹配单个字符
a:表示匹配字母a
\\:匹配转义字符"\"。
\t:匹配转义字符"\t"
\n:匹配转义字符"\n"
2、字符类:任意匹配里面的一个单个字符
[abc]:表示可能是字母a、字母或者字母c
[^abc]:表示不是字母a、b、c中的任意一个
[a-zA-Z]:表示全部字母中的任意一个
[0-9]:表示全部数字中的任意一个
3、边界匹配:在以后编写JavaScript的时候使用正则时会用到
^:表示一组正则的开始
$:表示一组正则的结束
4、简写表达式:每一位出现的简写标记也只表达一位
. :表示任意的一位字符(不包括换行符)
\d:表示任意的一个数字,等价于[0-9]
\D:表示任意的一位非数字,等价于[^0-9]
\w:表示任意的一位字母、数字、_,等价于[a-zA-Z0-9]
\W:表示任意的一位非字母、数字、_,等价于[^a-zA-Z0-9]
\s:表示任意的一位空格,例如,"\n"、"\t"等
\S:表示任意的一个非空格
\bword(\b):标注字符的边界(全字匹配)
5、限定符:之前的所有正则都是表示一位,如果想要表达多位,则就需要数量表示
正则表达式?:此正则出现0次或者1次
正则表达式*:此正则出现0次、1次或者多次
正则表达式+:此正则出现1次或者多次
正则表达式{n}:此正则出现正好n次
正则表达式{n,}:此正则出现n次以上
正则表达式{n,m}:此正则出现n~m次
6、逻辑表示:与、或、非
正则表达式A正则表达式B:表示表达式A之后紧跟着表达式B
正则表达式A|正则表达式B:表示表达式A或者是表达式B,二者任选一个出现
(正则表达式):将多个子表达式合成一个表示,作为一组出现
7、贪婪/懒惰匹配:
贪婪匹配<.+>:默认贪婪匹配“任意字符”
懒惰匹配<.+?>:懒惰匹配“任意字符”
//注:因为"."为元字符,所以将要将"."作为字符串时,应该使用转义字符"\"。
所以范例1的正则表达式"\\d+",其中"\\"为转义字符“\”,所以就是“\d”和“正则表达式+”,表示正则表达式(表示任意的一个数字)出现1次或者多次,换句话说就是“判断是否为多为数字”。
2、String类正则的支持
正则表达式主要是进行字符串数据分析,为方便进行正则处理,在Java中对String类提供了改进。在JDK 1.4后,String类对正则有了直接的方法支持,常见的方法如表 1所示。
方法名称 | 类型 | 描述 |
---|---|---|
public boolean mathes(String regex) | 普通 | 与指定正则匹配 |
public String replaceAll(String regex, String replacement) | 普通 | 替换满足指定正则的全部内容 |
public String replaceFirst(String regex, String replacement) | 普通 | 替换满足指定正则的首个内容 |
public String[] split(String regex) | 普通 | 按照指定正则则全拆分 |
public String[] split(String regex, int limit) | 普通 | 按照指定的正则拆分为指定个数 |
范例2:实现字符串替换(删除非字母与非数字)
package edu.zhku.test;
public class RegularExpressionTestDemo02 {
public static void main(String[] args) {
//要替换的原始数据
String string = "www(*@(####@)(12121)Java";
//删除 非字母[^a-zA-Z] 与 非数字[^0-9]
String regex = "[^a-zA-Z0-9]+";
System.out.println("删除非字母与非数字:" + string.replaceAll(regex, ""));
System.out.println("原字符串:" + string);
System.out.println("====================================");
//其他变形版
//删除 非字母[^a-zA-Z] 与 数字[0-9]
//非字母正则表达式:[^a-zA-Z]
String regex01 = "[^a-zA-Z]";
//数字正则表达式:[0-9]
String regex02 = "[0-9]";
//将满足正则表达式的字符串替换为了""(将数字字符串替换为"")
System.out.println("删除数字:" + string.replaceAll(regex02, ""));
System.out.println("原字符串:" + string);
System.out.println("====================================");
//将满足正则表达式的字符串替换为了""(将非字母字符串替换为"")
System.out.println("删除非字母:" + string.replaceAll(regex01, ""));
System.out.println("原字符串:" + string);
}
}
/*
删除非字母与非数字:www12121Java
原字符串:www(*@(####@)(12121)Java
====================================
删除数字:www(*@(####@)()Java
原字符串:www(*@(####@)(12121)Java
====================================
删除非字母:wwwJava
原字符串:www(*@(####@)(12121)Java
*/
本程序(除变形版)将字符串中所有非字母和非数字的内容通过正则进行匹配,由于可能包含有多个匹配内容,所以使用了“+”进行数量设置,并结合replaceAll()方法将匹配成功的内容替换为空格。
范例3:实现字符串拆分
package edu.zhku.test;
import java.util.Arrays;
//实现字符串拆分,保留数字内容
public class RegularExpressionTestDemo03 {
public static void main(String[] args) {
//定义原始数据
String string = "(09@*1a23bbc456efg*@&)";
System.out.println("原字符串:" + string);
System.out.println();
//定义正则
String regex = "[^0-9]+";
String[] strings = string.split(regex);
System.out.println(Arrays.toString(strings));
System.out.println();
System.out.println(strings.length);
System.out.println();
for (String s : strings) {
System.out.print(s + " ");
}
}
}
/*
程序执行结果:
原字符串:(09@*1a23bbc456efg*@&)
[, 09, 1, 23, 456]
5
09 1 23 456
*/
本程序通过正则匹配字符串中的非数字字符,通过spilt()方法实现数据的拆分操作。简单理解本例子就是,将不是数字的字符或者字符串舍去,得到的数据片段作为字符串数组的元素(注意:得到的元素可以为空字符"")。
范例4:判断一个数据是否为小数,如果是小数则将其转为double类型
package edu.blog.test02;
//一个数据是否为小数,如果是小数则将其转为double类型
public class RegularExpressionTestDemo04 {
public static void main(String[] args) {
//定义原始数据
String str01 = "22.22";
String str02 = "2222";
//定义正则
String regex = "\\d+\\.{1}\\d+";
//也可以定义为"\\d+(\\.\\d+)?"
System.out.println("原字符串str01:" + str01);
if (str01.matches(regex)) {
System.out.println(Double.parseDouble(str01));
} else {
System.out.println("不是小数");
}
System.out.println("==========");
System.out.println("原字符串str02:" + str02);
if (str02.matches(regex)) {
System.out.println(Double.parseDouble(str02));
} else {
System.out.println("不是小数");
}
}
}
/*
程序执行结果:
原字符串str01:22.22
22.22
==========
原字符串str02:2222
不是小数
*/
本程序在进行小数组成的正则判断需要考虑到小数点以及小数位的情况(即两者必须同时出现),其中部分正则表达式:"\\.{1}",表示小数点出现一次(注:因为".“为元字符,所以将要将”.“作为字符串时,应该使用转义字符”\")。
也可以将正则表达式定义为:"\\d+(\\.\\d+)?",即将小数点和小数位同时绑定,出现1次以上。
范例5:判断一个字符串是否由日期组成,如果是由日期组成则将其转为Date类型
package edu.blog.test02;
import java.text.ParseException;
import java.text.SimpleDateFormat;
//判断一个字符串是否由日期组成,如果是由日期组成则将其转为Date类型
public class RegularExpressionTestDemo05 {
public static void main(String[] args) throws ParseException {
//定义原始数据
String str01 = "2001-07-27";
//定义正则
String regex = "\\d{4}-\\d{2}-\\d{2}";
System.out.println("原字符串str01:" + str01);
if (str01.matches(regex)) {
System.out.println(new SimpleDateFormat("yyyy-MM-dd").parse(str01));
}else {
System.out.println("不是日期格式");
}
}
}
/*
程序执行结果:
原字符串str01:2001-07-27
Fri Jul 27 00:00:00 CST 2001
*/
本程序对给定的字符串进行日期格式检验,如果符合(只判断格式)则将字符串通过SimpleDateFormat类变为Date实例。
范例6:判断电话号码格式是否正确
package edu.blog.test02;
import java.text.ParseException;
import java.text.SimpleDateFormat;
/*
判断电话号码格式是否正确,本程序中电话号码的内容有以下4种情况:
电话号码类型1(7~8位数字):87654321 "\\d{7,8}"
电话号码类型2(在电话号码前追加区号):01087654321 "\\d{3,4}?\\d{7,8}"
电话号码类型3(区号单独包裹):(010)-87654321 "(\\(\\d{3,4}\\)-)?\\d{7,8}"
电话号码类型4(11位手机号码):12345678900 "\\d{11}"
综上:"(\\d{3,4})|(\\(\\d{3,4}\\)-)?\\d{7,8}|\\d{11}"
*/
public class RegularExpressionTestDemo06 {
public static void main(String[] args) throws ParseException {
//定义原始数据
String str01 = "87654321";
String str02 = "01087654321";
String str03 = "(010)-87654321";
String str04 = "12345678900";
//定义正则表达式
String regex = "(\\d{3,4})|(\\(\\d{3,4}\\)-)?\\d{7,8}|\\d{11}";
System.out.println("原字符串str01:" + str01);
System.out.println("原字符串str02:" + str02);
System.out.println("原字符串str03:" + str03);
System.out.println("原字符串str04:" + str04);
System.out.println("==================");
Utils.isTelephoneFormat(str01, regex);
Utils.isTelephoneFormat(str02, regex);
Utils.isTelephoneFormat(str03, regex);
Utils.isTelephoneFormat(str04, regex);
}
}
class Utils {
public static void isTelephoneFormat(String telephone, String regex) {
if (telephone.matches(regex)) {
System.out.println(telephone + " 是电话格式");
return;
}
System.out.println(telephone + " 不是电话格式");
}
}
/*
程序执行结果:
原字符串str01:87654321
原字符串str02:01087654321
原字符串str03:(010)-87654321
原字符串str04:12345678900
==================
87654321 是电话格式
01087654321 是电话格式
(010)-87654321 是电话格式
12345678900 是电话格式
*/
本程序通过一个正则表达式实现4种电话格式的匹配,在进行匹配时必须使用到“()”,所以需要使用“\\”的形式进行转义。
范例7:验证E-mail格式
package edu.blog.test02;
import java.text.ParseException;
/*
验证E-mail格式,现在要求一个合格的Email地址的组成规则如下:
1、E-mail的用户名可以由字母、数字、_所组成(不应该使用“_”开头) "[a-zA-Z0-9]\\w+"
2、E-mail的域名可以由字母、数字、_、-所组成 "\\w+"
3、域名的后缀必须是.cn、.com、.net、.com.cn、.gov "\\.(cn|com|net|com\\.cn|gov)"
格式:用户名+@+域名
例子:2222@163.com
*/
public class RegularExpressionTestDemo07 {
public static void main(String[] args) throws ParseException {
//定义原始数据
String str01 = "www123@qq.com";
String str02 = "_123@163.cn";
String str03 = "123@asdas.com.cn";
String str04 = "123@asasas.net";
String str05 = "123@asasas.gov";
String str06 = "123@asasas.com.cn.gov";
//定义正则
String regex = "[a-zA-Z0-9]\\w+" + "@" + "\\w+" + "\\.(cn|com|net|com\\.cn|gov)";
System.out.println("原字符串str01:" + str01);
System.out.println("原字符串str02:" + str02);
System.out.println("原字符串str03:" + str03);
System.out.println("原字符串str04:" + str04);
System.out.println("原字符串str05:" + str05);
System.out.println("原字符串str06:" + str06);
System.out.println("=====================================");
EmailUtils.isEmailFormat(str01, regex);
EmailUtils.isEmailFormat(str02, regex);
EmailUtils.isEmailFormat(str03, regex);
EmailUtils.isEmailFormat(str04, regex);
EmailUtils.isEmailFormat(str05, regex);
EmailUtils.isEmailFormat(str06, regex);
}
}
class EmailUtils {
public static void isEmailFormat(String email, String regex) {
if (email.matches(regex)) {
System.out.println(email + " 是电子邮件格式");
return;
}
System.out.println(email + " 不是电子邮件格式");
}
}
/*
程序执行结果:
原字符串str01:www123@qq.com
原字符串str02:_123@163.cn
原字符串str03:123@asdas.com.cn
原字符串str04:123@asasas.net
原字符串str05:123@asasas.gov
原字符串str06:123@asasas.com.cn.gov
=====================================
www123@qq.com 是电子邮件格式
_123@163.cn 不是电子邮件格式
123@asdas.com.cn 是电子邮件格式
123@asasas.net 是电子邮件格式
123@asasas.gov 是电子邮件格式
123@asasas.com.cn.gov 不是电子邮件格式
*/
本程序按给定的E-mail组成进行正则验证,正则匹配结构如图 2-1所示。
范例8:RGB颜色值匹配
package edu.blog.test02;
import java.text.ParseException;
//RGB颜色值匹配,输出符合RGB规则的字符串
public class RegularExpressionTestDemo08 {
public static void main(String[] args) throws ParseException {
//定义原始数据
String[] str01 = new String[]{
"#00",
"#ffffff",
"#ffaaff",
"#00hh00",
"#aabbcc",
"#000000",
"#fffffff"
};
//定义正则
String regex = "#[a-fA-F0-9]{6}\\b";
//输出满足正则的字符串
for (String string : str01) {
if (string.matches(regex)) {
System.out.println(string);
}
}
}
}
/*
程序执行结果:
#ffffff
#ffaaff
#aabbcc
#000000
*/
范例9:Ipv4地址匹配
package edu.blog.test02;
import java.text.ParseException;
//Ipv4地址匹配,输出符合Ipv4地址规则的字符串
public class RegularExpressionTestDemo09 {
public static void main(String[] args) throws ParseException {
//定义原始数据
String[] str01 = new String[]{
"123",
"255.255.255.0",
"192.168.0.1",
"0.0.0.0",
"256.1.1.1",
"123.123.0"
};
//定义正则
String regex = "\\b((25[0-5]|2[0-4]\\d|[01]?\\d?\\d?)\\.){3}(25[0-5]|2[0-4]\\d|[01]?\\d?\\d?)\\b";
//输出满足正则的字符串
for (String string : str01) {
if (string.matches(regex)) {
System.out.println(string);
}
}
}
}
/*
程序执行结果:
255.255.255.0
192.168.0.1
0.0.0.0
*/
3、java.util.regex包支持
String类提供的正则标记只提供了基础的实现功能,如果对于正则操作有更加严格要求就需要直接使用regex开发包中提供的类。java.util.regex从JDK 1.4开始正式提供的正则表达式开发包,在此包中定义有两个核心的正则操作类:Pattern(正则模式)和Matcher(匹配)。
java.util.regex.Pattern类的主要功能是进行正则表达式的编译以及获取Matcher类实例,其常用方法如表 3-2所示。
方法 | 类型 | 描述 |
---|---|---|
public static Pattern compile(String regex) | 普通 | 指定正则表达式规则 |
public Matcher matcher(CharSequence input) | 普通 | 获取Matcher类实例 |
public String[] split(CharSequence input) | 普通 | 字符串拆分 |
Pattern类并没有提供构造方法,如果想取得Pattern类实例,则必须调用compile()方法。对于字符串的格式验证与匹配的操作,则可以通过matcher()方法获取Matcher类实例化完成。Matcher类常用方法如表 3-2所示。
方法 | 类型 | 描述 |
---|---|---|
public boolean matches() | 普通 | 执行验证 |
public String replaceAll(String replacement) | 普通 | 字符串替换 |
public boolean find() | 普通 | 是否有下一个匹配 |
public String group(int group) | 普通 | 获取指定组编号的数据 |
范例1:使用Pattern类实现字符串拆分
package edu.blog.test02;
import java.util.regex.Pattern;
//使用Pattern类实现字符串拆分
public class RegexTestDemo01 {
public static void main(String[] args) {
//定义原始数据
String str01 = "Java##Linux**Python";
//定义正则表达式
String regex = "[^a-zA-Z]+";
//编译正则表达式
Pattern pattern = Pattern.compile(regex);
//字符串拆分
String[] result = pattern.split(str01);
for (String s : result) {
System.out.print(s + " ");
}
}
}
/*
程序执行结果:
Java Linux Python
*/
本程序通过Pattern类中的compile()方法编译并获取了给定正则表达式Pattern实例化对象,随后利用split()方法按照定义的正则进行拆分。
范例2:使用Matcher类实现正则验证
package edu.blog.test02;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
//使用Matcher类实现正则验证
public class RegexTestDemo02 {
public static void main(String[] args) {
//定义原始数据
String str01 = "2222";
//定义正则表达式
String regex = "\\d+";
//编译正则表达式
Pattern pattern = Pattern.compile(regex);
//获取Matcher实例化对象
Matcher matcher = pattern.matcher(str01);
System.out.println(matcher.matches());
}
}
/*
程序执行结果:
true
*/
本程序首先通过Pattern的实例化对象获取了Matcher类对象,这样便可匹配给定的正则对字符串的组成结构。
范例3:使用Matcher类实现字符串替换
package edu.blog.test02;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
//使用Matcher类实现字符串替换
public class RegexTestDemo03 {
public static void main(String[] args) {
//定义原始数据
String str01 = "12##Java45@@Python89!@#";
System.out.println("原字符串str01:" + str01);
//定义正则表达式
String regex = "[^a-zA-Z0-9]+";
//编译正则表达式
Pattern pattern = Pattern.compile(regex);
//获取Matcher实例化对象
Matcher matcher = pattern.matcher(str01);
//字符串替换
System.out.println(matcher.replaceAll(""));
}
}
/*
程序执行结果:
原字符串str01:12##Java45@@Python89!@#
12Java45Python89
*/
本程序使用Matcher类中replaceAll()方法将字符串中与正则匹配的内容全部替换为空字符串并输出。
范例4:使用Matcher类实现数据分组操作
package edu.blog.test02;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
//使用Matcher类实现数据分组操作
public class RegexTestDemo04 {
public static void main(String[] args) {
//定义原始数据
String str01 = "INSERT INTO dept{dept_id, dept_name,dept_age} VALUES (#{dept_id},#{dept_name},#{dept_age})";
System.out.println("原字符串str01:" + str01);
//定义正则表达式
String regex = "#\\{\\w+\\}";
//编译正则表达式
Pattern pattern = Pattern.compile(regex);
//获取Matcher实例化对象
Matcher matcher = pattern.matcher(str01);
//是否有匹配成功的内容
while (matcher.find()) {
String data = matcher.group(0).replaceAll("#|\\{|\\}", "");
System.out.print(data + " ");
}
}
}
/*
程序执行结果:
原字符串str01:INSERT INTO dept{dept_id, dept_name,dept_age} VALUES (#{dept_id},#{dept_name},#{dept_age})
dept_id dept_name dept_age
*/
本程序利用Matcher类提供的分组操作功能,将给定的完整字符串按照分组原则依次匹配并取出。
注:此文章为本人学习中记录的笔记,若有错误,敬请指正。