博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
正则表达式
阅读量:4049 次
发布时间:2019-05-25

本文共 5522 字,大约阅读时间需要 18 分钟。

-- Start

如果你还不知道什么是正则表达式或者不是很清楚,请先阅读

下面是一个在 Java 中使用正则表达式的简单例子。

import java.util.regex.Matcher;import java.util.regex.Pattern;public class Test {	public static void main(String[] args) {		// Pattern 表示一个正则表达式		// Pattern 的构造方法是私有的		// 可以通过 compile 静态方法实例化 Pattern 对象		// 在实例化的同时我们可以不指定或指定一个或多个全局匹配模式		// 下面的代码构建了用来匹配固定电话号码的正则表达式, 采用不区分大小写和多行模式		Pattern p = Pattern.compile("(\\d{3}\\d?)-(\\d{7}\\d?)", Pattern.CASE_INSENSITIVE|Pattern.DOTALL);						// 将构建好的正则表达式与目标字符串关联得到一个 Matcher 对象		Matcher m = p.matcher("我的电话号码是 0411-88888888, 欢迎骚扰。");						// find() 方法将会在目标字符串中查找符合正则表达式的子字符串, 如果找到则返回 true		// 再次调用 find() 方法将会在上次匹配的结束位置开始查找		// find(int start) 方法将从参数指定的位置开始查找符合正则表达式的子字符串		if (m.find()) {						// start() 方法返回整个匹配的起始位置			// end() 方法返回整个匹配的结束位置			// group() 方法返回匹配的内容, 			System.out.println("在目标字符串的 " + m.start() + " 到 " + m.end() + " 位置找到了 " + m.group());						// start(int group) 方法返回第group个捕获型括号匹配的起始位置			// end(int group) 方法返回第group个捕获型括号匹配的结束位置			// group(int group) 方法返回第group个捕获型括号匹配的内容			// groupCount() 返回捕获型括号的数目			System.out.println("在目标字符串的 " + m.start(1) + " 到 " + m.end(1) + " 位置找到了电话号码的区号 " + m.group(1));			System.out.println("在目标字符串的 " + m.start(2) + " 到 " + m.end(2) + " 位置找到了电话号码 " + m.group(2));					} else {			System.out.println("没有找到匹配的电话号码。");		}						// pattern() 方法返回当前 Matcher 使用的正则表达式 		// usePattern 方法用来更改和当前 Matcher 匹配的正则表达式		m.usePattern(Pattern.compile("\\w+@[.\\w]+")); // 用来匹配邮件地址						// reset(CharSequence input) 方法用来更改和当前 Matcher 匹配的字符串		m.reset("wave0409@163.com");						// matches 方法用来验证目标字符串是否和正则表达式完全匹配		// 而 find 方法是去目标字符串中查找符合正则表达式的子字符串		// lookingAt 方法非常类似matches 方法,但不要求完全匹配		if(m.matches()) {			System.out.println(m.group() + " 是一个合法的 Email 地址。");		}	}}

由此可见,在 Java 中使用正则表达式是非常简单的,我们只用到两个类 Pattern 和 Matcher。Pattern 对象表示一个正则表达式,在构建 Pattern 对象时,我们可以指定一个或多个全局匹配模式,Java 支持如下匹配模式。

全局匹配模式 局部匹配模式 描述
Pattern.UNIX_LINES d 只把\n作为换行符
Pattern.DOTALL s 点号能够匹配换行符
Pattern.MULTILINE m ^和$可以匹配字符串内部换行符
Pattern.COMMENTS x 注释模式
Pattern.CASE_INSENSITIVE i 对ASCII字符进行不区分大小写匹配
Pattern.UNICODE_CASE u 对Unicode字符进行不区分大小写匹配
Pattern.CANNON_EQ 不同的编码中相同的字符视为相等
Pattern.LITERAL 纯文本模式

之后我们可以将正则表达式与目标字符串关联得到一个 Matcher 对象,利用 Matcher 对象提供的方法我们可以对字符串进行查找、替换等操作。

 在上面的例子中,我们在整个目标字符串中查找能够匹配正则表达式的子字符串,事实上在应用正则表达式的时候,我们还可以指定目标字符串的检索范围,也就是说在目标字符串的子字符串中应用正则表达式。但此时会有一个问题,那就是 ^ 和 $ 应该匹配整个字符串的开头和结尾呢? 还是检索范围的起始和结束位置呢?Java 为我们提供了足够的灵活性,我们可以通过下面的方法来查看和设置,默认值是匹配检索范围的起始和结束位置。

hasAnchoringBounds()useAnchoringBounds(boolean b)

还有一个问题是是否允许环视和单词分界符等跨越检索范围,同样,Java 为我们提供了下面的方法来查看和设置。默认情况下是不允许的

hasTransparentBounds()useTransparentBounds(boolean b)

下面是一个简单的例子。

import java.util.regex.Matcher;import java.util.regex.Pattern;public class Test {	public static void main(String[] args) {		Pattern p = Pattern.compile("^\\d{3}\\d?-\\d{7}\\d?(?=,)");		Matcher m = p.matcher("我的电话号码是 0411-88888888, 欢迎骚扰。");						// region 方法设置正则表达式的检索范围		// regionStart() 方法返回检索范围的起始位置		// regionStart() 方法返回检索范围的结束位置		m.region(8, 21);		System.out.println("我们将在字符串的 " + m.regionStart() + " 到 " + m.regionEnd() + " 范围内应用正则表达式。");						// 设置环视可以突破检索范围,从而使表达式能够匹配成功		m.useTransparentBounds(true);		if (m.find()) {			System.out.println("在目标字符串的 " + m.start() + " 到 " + m.end() + " 位置找到了 " + m.group());		} else {			System.out.println("没有找到匹配的电话号码。");		}				// reset() 方法用来取消检索范围		m.reset();	}}

 上面我们介绍了如何进行查找操作, 下面我们通过一个例子看一下如何进行替换操作。

import java.util.regex.Matcher;import java.util.regex.Pattern;public class Test {	public static void main(String[] args) {		Pattern p = Pattern.compile("^.+(\\d{4}-\\d{8}).*$");		Matcher m = p.matcher("我的电话号码是 0411-88888888, 欢迎骚扰。");				// replaceAll 和 replaceFirst 方法用来执行替换操作		// 下面的替换操作将把电话号码从目标字符串中提取出来		String myPhoneNumber = m.replaceAll("$1");		System.out.println("我的电话是:" + myPhoneNumber);						// 在替换操作中 $ 符号用来反向引用		// 如果要替换的内容是从变量中传人的,而变量中恰好有 $ 符号,这将导致替换失败		// 因此在替换之前最好使用 quoteReplacement 方法转义参数		String salary = "$1000";		m.usePattern(Pattern.compile("\\d+"));		m.reset("我的工资是 1000");		String result = m.replaceFirst(Matcher.quoteReplacement(salary));		System.out.println(result);	}}

 上面的例子演示了一个简单的替换操作,下面的例子演示了一个高级的替换操作。

import java.util.regex.Matcher;import java.util.regex.Pattern;public class Test {	public static void main(String[] args) {		Pattern p = Pattern.compile("(\\d+)元");		Matcher m = p.matcher("我的工资是 1000元, 张三的工资是 1500元, 你的呢?");		StringBuffer result = new StringBuffer();		while(m.find()){			Double salary = Double.valueOf(m.group(1));			salary = salary / 6.3698; // 转换汇率			String replacement = String.format("%.2f美元", salary); // 保留2位小数						// 在每次 find 方法之后调用 appendReplacement			// 它将匹配之前的文本和要替换的内容添加到 result 中			// 第一次循环时,它将匹配之前的文本(我的工资是 )			// 和替换的内容(replacement)添加到 result 中			// 第二次循环时,它将匹配之前的文本(, 张三的工资是  )			// 和替换的内容(replacement)添加到 result 中			m.appendReplacement(result, replacement);		}				// 循环之后, appendTail 方法将剩余的文本添加到 result 中		m.appendTail(result);						// 打印结果		System.out.println(result);	}}

 上面两个关于替换的例子,我们并没有直接对原始字符串替换,而是返回替换后的结果,原始字符串并没有改变,如果原始字符串很长,这将严重影响性能,下面的例子演示了如何直接对原始字符串进行替换。

import java.util.regex.Matcher;import java.util.regex.Pattern;public class Test {	public static void main(String[] args) {		StringBuilder text = new StringBuilder("我的工资是 1000元, 张三的工资是 1500元, 你的呢?");		Pattern p = Pattern.compile("(\\d+)元");		Matcher m = p.matcher(text);		int matchPoint = 0;		while (m.find(matchPoint)) {			matchPoint = m.end();			text.replace(m.start(), m.end(), String.format("%.2f美元", Double.valueOf(m.group(1)) / 6.3698));		}				System.out.println(text);	}}

 

---更多参见:

-- 声 明:转载请注明出处
-- Last Updated on 2012-06-09
-- Written by ShangBo on 2012-06-04
-- End

你可能感兴趣的文章
MySQL数据库的高可用方案总结
查看>>
常用排序算法总结(一) 比较算法总结
查看>>
SSH原理与运用
查看>>
SIGN UP BEC2
查看>>
S3C2440中对LED驱动电路的理解
查看>>
《天亮了》韩红
查看>>
Windows CE下USB摄像头驱动开发(以OV511为例,附带全部源代码以及讲解) [转]
查看>>
模拟屏学习资料_什么是PAL制式
查看>>
模拟屏学习资料_模拟视频 入门
查看>>
西藏之旅
查看>>
Oracle中定时执行问题
查看>>
三时业
查看>>
佛教三宝-三皈依
查看>>
杂阿含经喻世间有四等马
查看>>
考研前夜涂笔
查看>>
英语复试自我介绍
查看>>
什么是熵?
查看>>
拼凑、摘抄-评李代平的软件工程第二版
查看>>
误传了数千年的几个名句
查看>>
韩复榘经典语录
查看>>