如果你曾经用过Perl或任何其他内建正则表达式支持的语言你一定知道用正则表达式处理文本和匹配模式是多么简单如果你不熟悉这个术语那么正则表达式(Regular Expression)就是一个字符构成的串它定义了一个用来搜索匹配字符串的模式
许多语言包括PerlPHPPythonjavascript和JScript都支持用正则表达式处理文本一些文本编辑器用正则表达式实现高级搜索替换功能那么Java又怎样呢?本文写作时一个包含了用正则表达式进行文本处理的Java规范需求(Specification Request)已经得到认可你可以期待在JDK的下一版本中看到它
然而如果现在就需要使用正则表达式又该怎么办呢?你可以从下载源代码开放的JakartaORO库本文接下来的内容先简要地介绍正则表达式的入门知识然后以JakartaORO API为例介绍如何使用正则表达式
一正则表达式基础知识
我们先从简单的开始假设你要搜索一个包含字符cat的字符串搜索用的正则表达式就是cat如果搜索对大小写不敏感单词catalogCatherinesophisticated都可以匹配也就是
句点符号
假设你在玩英文拼字游戏想要找出三个字母的单词而且这些单词必须以t字母开头以n字母结束另外假设有一本英文字典你可以用正则表达式搜索它的全部内容要构造出这个正则表达式你可以使用一个通配符——句点符号这样完整的表达式就是tn它匹配tantentin和ton还匹配t#ntpn甚至t n还有其他许多无意义的组合这是因为句点符号匹配所有字符包括空格Tab字符甚至换行符
方括号符号
为了解决句点符号匹配范围过于广泛这一问题你可以在方括号([])里面指定看来有意义的字符此时只有方括号里面指定的字符才参与匹配也就是说正则表达式t[aeio]n只匹配tanTentin和ton但Toon不匹配因为在方括号之内你只能匹配单个字符
或符号
如果除了上面匹配的所有单词之外你还想要匹配toon那么你可以使用|操作符|操作符的基本意义就是或运算要匹配toon使用t(a|e|i|o|oo)n正则表达式这里不能使用方扩号因为方括号只允许匹配单个字符这里必须使用圆括号()圆括号还可以用来分组具体请参见后面介绍
表示匹配次数的符号
表一显示了表示匹配次数的符号这些符号用来确定紧靠该符号左边的符号出现的次数
假设我们要在文本文件中搜索美国的社会安全号码这个号码的格式是用来匹配它的正则表达式如图一所示在正则表达式中连字符()有着特殊的意义它表示一个范围比如从到因此匹配社会安全号码中的连字符号时它的前面要加上一个转义字符\
图一匹配所有形式的社会安全号码
假设进行搜索的时候你希望连字符号可以出现也可以不出现——即和都属于正确的格式这时你可以在连字符号后面加上?数量限定符号如图二所示
图二匹配所有和形式的社会安全号码
下面我们再来看另外一个例子美国汽车牌照的一种格式是四个数字加上二个字母它的正则表达式前面是数字部分[]{}再加上字母部分[AZ]{}图三显示了完整的正则表达式
图三匹配典型的美国汽车牌照号码如KV
否符号
^符号称为否符号如果用在方括号内^表示不想要匹配的字符例如图四的正则表达式匹配所有单词但以X字母开头的单词除外
图四匹配所有单词但X开头的除外
圆括号和空白符号
假设要从格式为June 的生日日期中提取出月份部分用来匹配该日期的正则表达
图五匹配所有Moth DDYYYY格式的日期
新出现的\s符号是空白符号匹配所有的空白字符包括Tab字符如果字符串正确匹配接下来如何提取出月份部分呢?只需在月份周围加上一个圆括号创建一个组然后用ORO API(本文后面详细讨论)提取出它的值修改后的正则表达式如图六所示
图六匹配所有Month DDYYYY格式的日期定义月份值为第一个组
其它符号
为简便起见你可以使用一些为常见正则表达式创建的快捷符号如表二所示
表二常用符号
例如在前面社会安全号码的例子中所有出现[]的地方我们都可以使用\d修改后的正则表达式如图七所示
图七匹配所有格式的社会安全号码
二JakartaORO库
有许多源代码开放的正则表达式库可供Java程序员使用而且它们中的许多支持Perl 兼容的正则表达式语法我在这里选用的是JakartaORO正则表达式库它是最全面的正则表达式API之一而且它与Perl 正则表达式完全兼容另外它也是优化得最好的API之一
JakartaORO库以前叫做OROMatcherDaniel Savarese大方地把它赠送给了Jakarta Project你可以按照本文最后参考资源的说明下载它
我首先将简要介绍使用JakartaORO库时你必须创建和访问的对象然后介绍如何使用JakartaORO API
▲ PatternCompiler对象
首先创建一个PerlCompiler类的实例并把它赋值给PatternCompiler接口对象PerlCompiler是PatternCompiler接口的一个实现允许你把正则表达式编译成用来匹配的Pattern对象
▲ Pattern对象
要把正则表达式编译成Pattern对象调用compiler对象的compile()方法并在调用参数中指定正则表达式例如你可以按照下面这种方式编译正则表达式t[aeio]n
默认情况下编译器创建一个大小写敏感的模式(pattern)因此上面代码编译得到的模式只匹配tintan ten和ton但不匹配Tin和taN要创建一个大小写不敏感的模式你应该在调用编译器的时候指定一个额外的参数
创建好Pattern对象之后你就可以通过PatternMatcher类用该Pattern对象进行模式匹配
▲ PatternMatcher对象
PatternMatcher对象根据Pattern对象和字符串进行匹配检查你要实例化一个PerlMatcher类并把结果赋值给PatternMatcher接口PerlMatcher类是PatternMatcher接口的一个实现它根据Perl 正则表达式语法进行模式匹配
使用PatternMatcher对象你可以用多个方法进行匹配操作这些方法的第一个参数都是需要根据正则表达式进行匹配的字符串
·boolean matches(String input Pattern pattern)当输入字符串和正则表达式要精确匹配时使用换句话说正则表达式必须完整地描述输入字符串
·boolean matchesPrefix(String input Pattern pattern)当正则表达式匹配输入字符串起始部分时使用
·boolean contains(String input Pattern pattern)当正则表达式要匹配输入字符串的一部分时使用(即它必须是一个子串)
另外在上面三个方法调用中你还可以用PatternMatcherInput对象作为参数替代String对象这时你可以从字符串中最后一次匹配的位置开始继续进行匹配当字符串可能有多个子串匹配给定的正则表达式时用PatternMatcherInput对象作为参数就很有用了用PatternMatcherInput对象作为参数替代String时上述三个方法的语法如下
·boolean matches(PatternMatcherInput input Pattern pattern)
·boolean matchesPrefix(PatternMatcherInput input Pattern pattern)
·boolean contains(PatternMatcherInput input Pattern pattern)