实验简介
正则表达式(英语:Regular Expression,在代码中常简写为regex、regexp或RE)使用单个字符串来描述、匹配一系列符合某个句法规则的字符串搜索模式。搜索模式可用于文本搜索和文本替换。
正则表达式并不是某一门编程语言专用,它是一项独立于任何编程语言的一套文本搜索和匹配规则,目前是所有的程序设计语言都提供了对正则表达式标准规则的支持而已。
所以要学习好正则表达式,我们重点其实并不在于在某个程序设计语言中怎么调用,用什么函数,传递什么参数,而是首先要完全理解正则表达式的语法规则。
实验目的
1.掌握正则表达式的语法规则。
2.利用Java对字符串进行模式匹配。
3.利用正则表达式对WoniuATM进行输入验证。
实验流程
1.正则表达式语法规则
(1) 方括号:用于查找某个范围内的字符
表达式 | 描述 |
[abc] | 查找方括号之间的任何字符。 |
[^abc] | 查找任何不在方括号之间的字符。 |
[0-9] | 查找任何从 0 至 9 的数字。 |
[a-z] | 查找任何从小写 a 到小写 z 的字符。 |
[A-Z] | 查找任何从大写 A 到大写 Z 的字符。 |
[A-z] | 查找任何从大写 A 到小写 z 的字符。 |
[adgk] | 查找给定集合内的任何字符。 |
[^adgk] | 查找给定集合外的任何字符。 |
(red|blue|green) | 查找任何指定的选项,red或blue或green。 |
(2) 元字符:拥有特殊含义的字符
元字符 | 描述 |
. | 查找单个字符,除了换行和行结束符。 |
\w | 查找单词字符。 |
\W | 查找非单词字符。 |
\d | 查找数字。 |
\D | 查找非数字字符。 |
\s | 查找空白字符。 |
\S | 查找非空白字符。 |
\b | 匹配单词边界。 |
\B | 匹配非单词边界。 |
\0 | 查找 NUL 字符。 |
\n | 查找换行符。 |
\f | 查找换页符。 |
\r | 查找回车符。 |
\t | 查找制表符。 |
\v | 查找垂直制表符。 |
\xxx | 查找以八进制数 xxx 规定的字符。 |
\xdd | 查找以十六进制数 dd 规定的字符。 |
\uxxxx | 查找以十六进制数 xxxx 规定的 Unicode 字符。 |
(3) 量词:解决匹配数量的问题
量词 | 描述 |
n+ | 匹配任何包含至少一个 n 的字符串。 |
n* | 匹配任何包含零个或多个 n 的字符串。 |
n? | 匹配任何包含零个或一个 n 的字符串。 |
n{X} | 匹配包含 X 个 n 的序列的字符串。 |
n{X,Y} | 匹配包含 X 或 Y 个 n 的序列的字符串。 |
n{X,} | 匹配包含至少 X 个 n 的序列的字符串。 |
n$ | 匹配任何结尾为 n 的字符串。 |
^n | 匹配任何开头为 n 的字符串。 |
?=n | 匹配任何其后紧接指定字符串 n 的字符串。 |
?!n | 匹配任何其后没有紧接指定字符串 n 的字符串。 |
2.Java代码实现
package com.woniuxy.java.basic;
import java.util.regex.Matcher; import java.util.regex.Pattern;
public class RegExUsage { public static void main(String[] args) { RegExUsage re = new RegExUsage(); re.match(); }
// 是否匹配 public void match() { String phone = "15681223235"; // 电话号码验证规则 String phoneEx = "^1[3578]\\d{9}$"; // String phoneEx2 = "1(3|5|7|8)[0-9]{7,10}"; // 编译正则表达式 Pattern pattern = Pattern.compile(phoneEx); // 忽略大小写的写法 // Pattern pat = Pattern.compile(regEx, Pattern.CASE_INSENSITIVE); Matcher matcherPhone = pattern.matcher(phone); // 字符串是否与正则表达式相匹配 boolean rs = matcherPhone.matches(); System.out.println("手机验证:" + rs); // 邮箱验证规则 String email = "dengqiang@quangtruong.net"; String emailEx = "^[A-Za-z0-9][a-zA-Z0-9_]{1,}@ (([a-zA-z0-9]-*){1,}\\.){1,3}[a-zA-z\\-]{1,3}"; System.out.println("邮箱验证:"+Pattern.compile(emailEx). matcher(email).matches()); // 中国的座机号码:0512-85121234, 028-65656543, 0371-3456788 String telephone = "0512-8512123"; String telephoneEx = "^0\\d{2,3}-[856]\\d{6,7}$"; System.out.println("座机验证:"+Pattern.compile(telephoneEx). matcher(telephone).matches()); } } |
3.根据左右边界查找中间内容
在后续的实验中,除了利用正则表达式进行匹配确认外,我们还会大量使用正则表达来根据指定的左右边界查找其中间部分夹着的内容。所以我们来看看如何利用Matcher对象的find()方法查找相应的内容,代码如下:
public void findByLefeRight() { String source = "<input name='verify' value='5AC8E6D2' type='hidden'/>"; // 左边界为:value=',右边界为:' type,查找到的值为5AC8E6D2 String regEx = "(value=')(.+)(' type)"; String tmp = ""; Pattern p = Pattern.compile(regEx); Matcher m = p.matcher(source); if (m.find()) tmp = m.group(2); System.out.println(tmp); } |
上述正则表达式“(value=')(.+)(' type)”中的“.+”是指被左右边界夹着的内容至少有一个字符即可,可以适配除了“换行符或结束符”之外的其它任意字符。
但是问题恰恰就出在这里,如果我们要查找的内容中有换行符,或者左边界在后面的行,则正则表达式无法完成匹配。
比如我们将字符串“5AC8E6D2”后面加上一个“\n”对字符串进行换行,那么右边界“’ type”则在下一行,此时是无法查找到“5AC8E6D2”这一段内容的。所以我们的解决方案是为正则表达式的匹配模式设置为支持换行,可将代码修改为如下方式即可:
public void findByLefeRight() { String source = "<input name='verify' value='5AC8E6D2\n' type='hidden'/>"; // 左边界为:value=',右边界为:' type,查找到的值为5AC8E6D2 String regEx = "(value=')(.+)(' type)"; String tmp = ""; // 设置支持正则表达式“.”支持匹配换行符 Pattern p = Pattern.compile(regEx, Pattern.DOTALL); Matcher m = p.matcher(source); if (m.find()) tmp = m.group(2); System.out.println(tmp); } |
另外一个方面需要注意的是,由于在一个文本内容中通过指定左右边界进行查找,但是该内容里面可以包含多个左右边界,此时如果我们使用“.+”进行匹配的话,正则表达式会优先匹配尽可能长的内容,比如匹配到最后一个右边界的内容。
有可能这并不是我们想要的内容,我们希望是匹配离左边界最近的右边界中间的内容,此时我们需要使用“非贪婪模式”进行区别,将“.+”修改为“.+?”即可。
思考练习
1.请利用正则表达式完成对WoniuATM的用户输入,如选项,电话号码,金额等的检查。
2.请利用正则表达式从一个文本文件中查找指定左右边界的中间部分内容。