Java操作正则表达式
编程中,有一类任务十分常见。那就是需要在一个串中查找具有某种特定样式的子串。通常采用直接编程--对母串进行过滤的方法。此法虽说原理简单、控制直观,但当条件较复杂时,代码较多,且十分容易因考虑不周而出错。实际上,我们完全可以使用现成的技术--正则表达式,来解决这一棘手的问题。
正则表达式并非Java中独有。它几乎是一门独立的语言,有着完备的语法和描述策略。其表述功能十分强大,可以比为串处理中的sql语句。
我们常用正则表达式来处理下列的问题:
1. 判断一个串是否与我们设想的“样式”一致。显然,它的输出结果是个boolean类型。
2. 在一个母串中查找我们要求的子串,需要取得它出现的位置,以及子串的值。
3. 用给定的样式搜索母串。把搜索到的子串替换为其它的内容。
java.util.regex 包提供了对正则表达式的支持。
问题1:判断是否匹配。
下例判断了一个串是否为有效的十六进制常量表示。
0xAB1D,0xCCE9,0x123ed 都是正确的。而 abcd,0x12FX 等不正确。
代码如下:
import java.util.regex.*;
public class RegexTest
{
public static void main(String[] args)
{
String s = "0xAB12"; // 待判定的串
String p = "0[xX][0-9a-fA-F]+"; // 所要求的样式
System.out.println(Pattern.matches(p,s));
}
}
这里的 "0[xX][0-9a-fA-F]+" 即是正则表达式的写法。它的意思是:以0开始,接下来的字母是x或X,接下来是另一个符出现至少一次,至多不限。这“另一个”字符的要求是:0-9的数字或者a-f的大写或小字母。
方括号中括起来的东西表示一个字符。其中如列出多个,它们之间是“或者”的关系,也可以用“|”符号表达或者。这样一来,[xX] 也可以表示为:(x|X)。此处的小括号是用于表达结合关系或说优先级的,与四则运算中的小括号一样(小括号还有其它更高级的用法)。由此可推知:[a-f]的意思是:(a|b|c|d|e|f)。
最后的一个“+”号表示前一个元素出现的次数限制。可以有一个大括号表示:
{1,10} 的意思是:最少出现一次,最多10次。
{2, } 的意思是最多不限,最少两次。
{4} 的意思是正好出现4次。
+ 的意思是: {1, },即最少出现一次
* 的意思是: 任意多次(也可以是零次)
? 的意思是: {0,1},即出现或者不出现
需要注意的是,如果要查找的东西恰好是 + ? 等这样的字符本身,就需要转义。因为它们是正则表达式中的“关键字”。转义的方法与Java中串的转义方法一样,就是用:“/”。
一个整数的加法算式的模式是:[0-9]+/+[0-9]+
写在Java的串就成了:String p = "[0-9]+//+[0-9]+";
为什么要写两个 “/”呢?因为反斜杠同时也是Java中串的转义符。
根所正则表达式的语法,这里的[0-9]也可以写为:“/d”。如果使用这个方式,在Java的串中,看起来就有点怪怪的了。形如:"//d+//+//d+"。
如果我们也允许加法算式的前边或后边可以有一些空格。就需要如下形状:
问题2:求模式子串位置和值
String s1 = "56+14-5*(2+6)-56+48";
String s2 = "//+|//-|//*|///|//(|//)";
Pattern p = Pattern.compile(s2);
Matcher m = p.matcher(s1);
while(m.find()){
System.out.println(m.group() + "," + m.start() + "," + m.end());
}
上例中,寻找 +-*/ 及括号的位置,输出匹配项,并其起始和结束位置。
Matcher类代表一个遍历串的匹配工具。它用 find() 搜索下一个匹配项,group() 输出匹配项的内容,start(), end() 给出匹配项出现的开始和结束位置。
问题3:对匹配项进行替换
String s1 = "2+5*3/5-4";
String s2 = "[0-9]{1,2}//*[0-9]{1,2}|[0-9]{1,2}///[0-9]{1,2}";
Pattern p = Pattern.compile(s2);
Matcher m = p.matcher(s1);
if(m.find()){
String t = m.group();
s1 = m.replaceFirst("kkk");
}
System.out.println(s1);
上面的代码,在s1中搜索第一个出现的乘法或除法算式,并把它用“kkk”去代替。此处,replaceFirst()方法,把第一处匹配用另一个串去代替。这个方法很有用。我们可以利用这个动作去对四则运算求值。