正则表达式

-- 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_LINESd只把\n作为换行符
Pattern.DOTALLs点号能够匹配换行符
Pattern.MULTILINEm^和$可以匹配字符串内部换行符
Pattern.COMMENTSx注释模式
Pattern.CASE_INSENSITIVEi对ASCII字符进行不区分大小写匹配
Pattern.UNICODE_CASEu对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);
	}

}

 

---更多参见:Java 精萃
-- 声 明:转载请注明出处
-- Last Updated on 2012-06-09
-- Written by ShangBo on 2012-06-04
-- End


  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值