`
yuexiaowen
  • 浏览: 124720 次
  • 性别: Icon_minigender_2
  • 来自: 咸阳
社区版块
存档分类
最新评论

正则表达式学习

    博客分类:
  • java
阅读更多

Java正则表达式详解


仙人掌工作室
01-7-31 下午 04:13:03

 

如果你曾经用过Perl或任何其他内建正则表达式支持的语言,你一定知道用正则表达式处理文本和匹配模式是多么简单。如果你不熟悉这个术语,那么“正则表达式”(Regular Expression)就是一个字符构成的串,它定义了一个用来搜索匹配字符串的模式。
许多语言,包括Perl、PHP、Python、JavaScript和JScript,都支持用正则表达式处理文本,一些文本编辑器用正则表达式实现高级“搜索-替换”功能。那么Java又怎样呢?本文写作时,一个包含了用正则表达式进行文本处理的Java规范需求(Specification Request)已经得到认可,你可以期待在JDK的下一版本中看到它。
然而,如果现在就需要使用正则表达式,又该怎么办呢?你可以从Apache.org下载源代码开放的Jakarta-ORO库。本文接下来的内容先简要地介绍正则表达式的入门知识,然后以Jakarta-ORO API为例介绍如何使用正则表达式。
一、正则表达式基础知识
我们先从简单的开始。假设你要搜索一个包含字符“cat”的字符串,搜索用的正则表达式就是“cat”。如果搜索对大小写不敏感,单词“catalog”、“Catherine”、“sophisticated”都可以匹配。也就是说:
1.1 句点符号
假设你在玩英文拼字游戏,想要找出三个字母的单词,而且这些单词必须以“t”字母开头,以“n”字母结束。另外,假设有一本英文字典,你可以用正则表达式搜索它的全部内容。要构造出这个正则表达式,你可以使用一个通配符——句点符号“.”。这样,完整的表达式就是“t.n”,它匹配“tan”、 “ten”、“tin”和“ton”,还匹配“t#n”、“tpn”甚至“t n”,还有其他许多无意义的组合。这是因为句点符号匹配所有字符,包括空格、Tab字符甚至换行符:
1.2 方括号符号
为了解决句点符号匹配范围过于广泛这一问题,你可以在方括号(“[]”)里面指定看来有意义的字符。此时,只有方括号里面指定的字符才参与匹配。也就是说,正则表达式“t[aeio]n”只匹配“tan”、“Ten”、“tin”和“ton”。但“Toon”不匹配,因为在方括号之内你只能匹配单个字符:
1.3 “或”符号
如果除了上面匹配的所有单词之外,你还想要匹配“toon”,那么,你可以使用“|”操作符。“|”操作符的基本意义就是“或”运算。要匹配 “toon”,使用“t(a|e|i|o|oo)n”正则表达式。这里不能使用方扩号,因为方括号只允许匹配单个字符;这里必须使用圆括号“()”。圆括号还可以用来分组,具体请参见后面介绍。
1.4 表示匹配次数的符号
表一显示了表示匹配次数的符号,这些符号用来确定紧靠该符号左边的符号出现的次数:

假设我们要在文本文件中搜索美国的社会安全号码。这个号码的格式是999-99-9999。用来匹配它的正则表达式如图一所示。在正则表达式中,连字符(“-”)有着特殊的意义,它表示一个范围,比如从0到9。因此,匹配社会安全号码中的连字符号时,它的前面要加上一个转义字符“\”。

图一:匹配所有123-12-1234形式的社会安全号码

假设进行搜索的时候,你希望连字符号可以出现,也可以不出现——即,999-99-9999和999999999都属于正确的格式。这时,你可以在连字符号后面加上“?”数量限定符号,如图二所示:

图二:匹配所有123-12-1234和123121234形式的社会安全号码

下面我们再来看另外一个例子。美国汽车牌照的一种格式是四个数字加上二个字母。它的正则表达式前面是数字部分“[0-9]{4}”,再加上字母部分“[A-Z]{2}”。图三显示了完整的正则表达式。

图三:匹配典型的美国汽车牌照号码,如8836KV

1.5 “否”符号
“^”符号称为“否”符号。如果用在方括号内,“^”表示不想要匹配的字符。例如,图四的正则表达式匹配所有单词,但以“X”字母开头的单词除外。

图四:匹配所有单词,但“X”开头的除外

1.6 圆括号和空白符号
假设要从格式为“June 26, 1951”的生日日期中提取出月份部分,用来匹配该日期的正则表达式可以如图五所示:

图五:匹配所有Moth DD,YYYY格式的日期

新出现的“\s”符号是空白符号,匹配所有的空白字符,包括Tab字符。如果字符串正确匹配,接下来如何提取出月份部分呢?只需在月份周围加上一个圆括号创建一个组,然后用ORO API(本文后面详细讨论)提取出它的值。修改后的正则表达式如图六所示:

图六:匹配所有Month DD,YYYY格式的日期,定义月份值为第一个组

1.7 其它符号
为简便起见,你可以使用一些为常见正则表达式创建的快捷符号。如表二所示:
表二:常用符号

例如,在前面社会安全号码的例子中,所有出现“[0-9]”的地方我们都可以使用“\d”。修改后的正则表达式如图七所示:

图七:匹配所有123-12-1234格式的社会安全号码

二、Jakarta-ORO库
有许多源代码开放的正则表达式库可供Java程序员使用,而且它们中的许多支持Perl 5兼容的正则表达式语法。我在这里选用的是Jakarta-ORO正则表达式库,它是最全面的正则表达式API之一,而且它与Perl 5正则表达式完全兼容。另外,它也是优化得最好的API之一。
Jakarta-ORO库以前叫做OROMatcher,Daniel Savarese大方地把它赠送给了Jakarta Project。你可以按照本文最后参考资源的说明下载它。
我首先将简要介绍使用Jakarta-ORO库时你必须创建和访问的对象,然后介绍如何使用Jakarta-ORO API。
▲ PatternCompiler对象
首先,创建一个Perl5Compiler类的实例,并把它赋值给PatternCompiler接口对象。Perl5Compiler是PatternCompiler接口的一个实现,允许你把正则表达式编译成用来匹配的Pattern对象。
▲ Pattern对象
要把正则表达式编译成Pattern对象,调用compiler对象的compile()方法,并在调用参数中指定正则表达式。例如,你可以按照下面这种方式编译正则表达式“t[aeio]n”:
默认情况下,编译器创建一个大小写敏感的模式(pattern)。因此,上面代码编译得到的模式只匹配“tin”、“tan”、 “ten”和“ton”,但不匹配“Tin”和“taN”。要创建一个大小写不敏感的模式,你应该在调用编译器的时候指定一个额外的参数:
创建好Pattern对象之后,你就可以通过PatternMatcher类用该Pattern对象进行模式匹配。
▲ PatternMatcher对象
PatternMatcher对象根据Pattern对象和字符串进行匹配检查。你要实例化一个Perl5Matcher类并把结果赋值给 PatternMatcher接口。Perl5Matcher类是PatternMatcher接口的一个实现,它根据Perl 5正则表达式语法进行模式匹配:
使用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)
三、应用实例
下面我们来看看Jakarta-ORO库的一些应用实例。
3.1 日志文件处理
任务:分析一个Web服务器日志文件,确定每一个用户花在网站上的时间。在典型的BEA WebLogic日志文件中,日志记录的格式如下:
分析这个日志记录,可以发现,要从这个日志文件提取的内容有两项:IP地址和页面访问时间。你可以用分组符号(圆括号)从日志记录提取出IP地址和时间标记。
首先我们来看看IP地址。IP地址有4个字节构成,每一个字节的值在0到255之间,各个字节通过一个句点分隔。因此,IP地址中的每一个字节有至少一个、最多三个数字。图八显示了为IP地址编写的正则表达式:

图八:匹配IP地址

IP地址中的句点字符必须进行转义处理(前面加上“\”),因为IP地址中的句点具有它本来的含义,而不是采用正则表达式语法中的特殊含义。句点在正则表达式中的特殊含义本文前面已经介绍。
日志记录的时间部分由一对方括号包围。你可以按照如下思路提取出方括号里面的所有内容:首先搜索起始方括号字符(“[”),提取出所有不超过结束方括号字符(“]”)的内容,向前寻找直至找到结束方括号字符。图九显示了这部分的正则表达式。

图九:匹配至少一个字符,直至找到“]”

现在,把上述两个正则表达式加上分组符号(圆括号)后合并成单个表达式,这样就可以从日志记录提取出IP地址和时间。注意,为了匹配“- -”(但不提取它),正则表达式中间加入了“\s-\s-\s”。完整的正则表达式如图十所示。

图十:匹配IP地址和时间标记

现在正则表达式已经编写完毕,接下来可以编写使用正则表达式库的Java代码了。
为使用Jakarta-ORO库,首先创建正则表达式字符串和待分析的日志记录字符串:
这里使用的正则表达式与图十的正则表达式差不多完全相同,但有一点例外:在Java中,你必须对每一个向前的斜杠(“\”)进行转义处理。图十不是 Java的表示形式,所以我们要在每个“\”前面加上一个“\”以免出现编译错误。遗憾的是,转义处理过程很容易出现错误,所以应该小心谨慎。你可以首先输入未经转义处理的正则表达式,然后从左到右依次把每一个“\”替换成“\\”。如果要复检,你可以试着把它输出到屏幕上。
初始化字符串之后,实例化PatternCompiler对象,用PatternCompiler编译正则表达式创建一个Pattern对象:
现在,创建PatternMatcher对象,调用PatternMatcher接口的contain()方法检查匹配情况:
接下来,利用PatternMatcher接口返回的MatchResult对象,输出匹配的组。由于logEntry字符串包含匹配的内容,你可以看到类如下面的输出:
3.2 HTML处理实例一
下面一个任务是分析HTML页面内FONT标记的所有属性。HTML页面内典型的FONT标记如下所示:
程序将按照如下形式,输出每一个FONT标记的属性:
在这种情况下,我建议你使用两个正则表达式。第一个如图十一所示,它从字体标记提取出“"face="Arial, Serif" size="+2" color="red"”。

图十一:匹配FONT标记的所有属性

第二个正则表达式如图十二所示,它把各个属性分割成名字-值对。

图十二:匹配单个属性,并把它分割成名字-值对

分割结果为:
现在我们来看看完成这个任务的Java代码。首先创建两个正则表达式字符串,用Perl5Compiler把它们编译成Pattern对象。编译正则表达式的时候,指定Perl5Compiler.CASE_INSENSITIVE_MASK选项,使得匹配操作不区分大小写。
接下来,创建一个执行匹配操作的Perl5Matcher对象。
假设有一个String类型的变量html,它代表了HTML文件中的一行内容。如果html字符串包含FONT标记,匹配器将返回true。此时,你可以用匹配器对象返回的MatchResult对象获得第一个组,它包含了FONT的所有属性:
接下来创建一个PatternMatcherInput对象。这个对象允许你从最后一次匹配的位置开始继续进行匹配操作,因此,它很适合于提取FONT标记内属性的名字-值对。创建PatternMatcherInput对象,以参数形式传入待匹配的字符串。然后,用匹配器实例提取出每一个FONT的属性。这通过指定PatternMatcherInput对象(而不是字符串对象)为参数,反复地调用PatternMatcher对象的contains ()方法完成。PatternMatcherInput对象之中的每一次迭代将把它内部的指针向前移动,下一次检测将从前一次匹配位置的后面开始。
本例的输出结果如下:
3.3 HTML处理实例二
下面我们来看看另一个处理HTML的例子。这一次,我们假定Web服务器从widgets.acme.com移到了newserver.acme.com。现在你要修改一些页面中的链接:
执行这个搜索的正则表达式如图十三所示:

图十三:匹配修改前的链接

如果能够匹配这个正则表达式,你可以用下面的内容替换图十三的链接:
注意#字符的后面加上了$1。Perl正则表达式语法用$1、$2等表示已经匹配且提取出来的组。图十三的表达式把所有作为一个组匹配和提取出来的内容附加到链接的后面。
现在,返回Java。就象前面我们所做的那样,你必须创建测试字符串,创建把正则表达式编译到Pattern对象所必需的对象,以及创建一个PatternMatcher对象:
接下来,用com.oroinc.text.regex包Util类的substitute()静态方法进行替换,输出结果字符串:
Util.substitute()方法的语法如下:
这个调用的前两个参数是以前创建的PatternMatcher和Pattern对象。第三个参数是一个Substiution对象,它决定了替换操作如何进行。本例使用的是Perl5Substitution对象,它能够进行Perl5风格的替换。第四个参数是想要进行替换操作的字符串,最后一个参数允许指定是否替换模式的所有匹配子串(Util.SUBSTITUTE_ALL),或只替换指定的次数。

【结束语】 在这篇文章中,我为你介绍了正则表达式的强大功能。只要正确运用,正则表达式能够在字符串提取和文本修改中起到很大的作用。另外,我还介绍了如何在Java 程序中通过Jakarta-ORO库利用正则表达式。至于最终采用老式的字符串处理方式(使用StringTokenizer,charAt,和 substring),还是采用正则表达式,这就有待你自己决定了。

Java代码 复制代码
  1. package com.systop;<BR>   
  2. import java.io.*;<BR>   
  3. import java.net.*;<BR>   
  4. import java.util.regex.*;<BR>   
  5. <BR>   
  6. /**<BR>  
  7.  This program displays all URLs in a web page by<BR>  
  8.  matching a regular expression that describes the<BR>  
  9.  <a href=...> HTML tag. Start the program as<BR>  
  10.  java HrefMatch URL<BR>  
  11.  */<BR>   
  12. public class HelloTest {<BR>   
  13.     public static void main(String[] args) {<BR>   
  14.         try {<BR>   
  15.             // get URL string from command line or use default<BR>   
  16.             String urlString;<BR>   
  17.             if (args.length > 0)<BR>   
  18.                 urlString = args[0];<BR>   
  19.             else<BR>   
  20.                 urlString = "http://www.sina.com";<BR>   
  21. <BR>   
  22.             // open reader for URL<BR>   
  23.             InputStreamReader in = new InputStreamReader(new URL(urlString)<BR>   
  24.                     .openStream());<BR>   
  25. <BR>   
  26.             // read contents into string buffer<BR>   
  27.             StringBuilder input = new StringBuilder();<BR>   
  28.             int ch;<BR>   
  29.             while ((ch = in.read()) != -1)<BR>   
  30.                 input.append((char) ch);<BR>   
  31. <BR>   
  32.             // search for all occurrences of pattern<BR>   
  33.             String patternString = "<a\\s+href\\s*=\\s*(\"[^\"]*\"|[^\\s>])\\s*>";<BR>   
  34.             Pattern pattern = Pattern.compile(patternString,<BR>   
  35.                     Pattern.CASE_INSENSITIVE);<BR>   
  36.             Matcher matcher = pattern.matcher(input);<BR>   
  37. <BR>   
  38.             while (matcher.find()) {<BR>   
  39.                 int start = matcher.start();<BR>   
  40.                 int end = matcher.end();<BR>   
  41.                 String match = input.substring(start, end);<BR>   
  42.                 System.out.println(matcher.group(1));<BR>   
  43.                 System.out.println(match);<BR>   
  44.             }<BR>   
  45.         } catch (IOException e) {<BR>   
  46.             e.printStackTrace();<BR>   
  47.         } catch (PatternSyntaxException e) {<BR>   
  48.             e.printStackTrace();<BR>   
  49.         }<BR>   
  50.     }<BR>   
  51. }  
分享到:
评论

相关推荐

    正则表达式学习心得 v1.0

    ### 正则表达式学习心得 v1.0 #### 摘要与目的 本文旨在分享作者在学习正则表达式过程中的心得体验,并重点介绍了几种常见编程语言(Python、C#、PHP)及文本编辑器(Notepad++)中正则表达式的使用技巧。此外,还...

    正则表达式学习工具

    本“正则表达式学习工具”是专为C#初学者和开发者设计的,旨在提供一个方便的环境来学习和测试正则表达式。 首先,我们来了解C#中的正则表达式基础。C#中的正则表达式操作主要通过`System.Text.RegularExpressions`...

    正则表达式学习资料以及练习项目代码很多

    这个压缩包包含了丰富的正则表达式学习资源,适合有一定基础的初学者深入学习。 1. **基础概念** - **模式匹配**:正则表达式定义了一种模式,可以用来匹配符合该模式的字符串。 - **元字符**:如`.`代表任意单个...

    正则表达式学习资料整理

    在这个“正则表达式学习资料整理”中,我们主要探讨的是如何理解和运用正则表达式进行四则运算相关的匹配。 首先,我们需要了解正则表达式的基本构成元素。它们包括: 1. **字符类**:用方括号`[]`定义,如 `[0-9]...

    正则表达式全解及正则表达式学习心得

    正则表达式全解及正则表达式学习心得 正则表达式是字符串模式匹配的强大工具,掌握正则表达式可以让开发者更方便地处理字符串数据。本文将对正则表达式的基本概念、元字符、模式匹配、量词、分组、字符类、边界匹配...

    java正则表达式学习

    【Java正则表达式学习】 Java正则表达式是Java编程语言中用于处理字符串的强大工具,自JDK1.4版本起被引入。它源于PHP并迅速流行,主要用于复杂字符串的验证和处理。正则表达式可以高效地完成对字符串的检查、分割...

    正则表达式学习手册

    ### 正则表达式学习手册知识点总结 #### 1. 引言 正则表达式是一种强大的文本处理工具,能够帮助用户实现字符串的查找、替换等功能。正则表达式的应用场景非常广泛,尤其在编程领域中不可或缺。对于初学者来说,...

    正则表达式学习书PDF

    在"正则表达式学习书PDF"这个资源中,包含两本关于正则表达式的教程: 1. **《正则表达式必知必会》** 这本书通常会深入浅出地介绍正则表达式的概念和用法,包括基本字符类(如字母、数字、空白符)、量词(如*、+...

    正则表达式学习视频

    在正则表达式的简单语法部分,你将学习到: 1. 基本字符匹配:如点号(.)匹配任意单个字符,星号(*)表示前面的元素可以重复零次或多次。 2. 字符集合:使用方括号([])定义一个字符集,如[a-z]匹配所有小写字母。...

    易语言正则表达式学习工具源码

    易语言正则表达式学习工具源码是一款专为学习易语言和正则表达式设计的软件开发资源。正则表达式(Regular Expression)是用于处理字符串的强大工具,它在编程中有着广泛的应用,如文本搜索、替换、数据验证等。...

    正则表达式学习课件PPT

    本课件“正则表达式学习课件PPT”旨在为初学者提供一个基础的正则表达式学习平台,特别地,通过使用C#语言来演示其应用。 首先,我们需要理解正则表达式的基础语法。正则表达式由一系列特殊字符和普通字符组成,...

    正则表达式学习资料

    在这个"正则表达式学习资料"中,我们将深入探讨正则表达式的基本概念、语法以及在Java中的应用。 1. 正则表达式基础: - **模式匹配**:正则表达式是由字符和特殊符号组成的字符串,用于定义一种模式,可以用来...

    正则表达式学习,常用的正则表达式

    正则表达式学习 正则表达式是计算机科学中的一种形式语言,它通过字符串操作来描述、匹配和处理字符串的方式。正则表达式通常用于文本搜索、匹配、替换、筛选等操作。 正则表达式简介 正则表达式的主要功能是对...

    正则表达式 学习 全收集 chm pdf 正则表达式验证工具 exe

    正则表达式 学习 全收集 chm pdf 正则表达式验证工具 exe正则表达式 学习 全收集 chm pdf 正则表达式验证工具 exe正则表达式 学习 全收集 chm pdf 正则表达式验证工具 exe正则表达式 学习 全收集 chm pdf 正则表达式...

    正则表达式学习笔记

    ### 正则表达式学习笔记 #### 一、正则表达式概述 正则表达式是一种强有力的模式匹配工具,广泛应用于各种编程语言中,用于文本处理。正则表达式允许用户定义复杂的查找模式,这对于数据验证、搜索和替换操作特别...

    正则表达式 必知必会 pdf

    它的出版,为程序员和开发人员提供了一本实用性强的正则表达式学习资源。本书基于各种实用场景,从基础的文本匹配开始,逐步深入到回溯引用、条件性求值以及前后查找等高级特性,使得读者能够系统、全面地掌握正则...

    vb正则表达式实例(正则表达式测试程序)

    在VB.NET中,正则表达式...总之,“vb正则表达式实例”是一个实用的工具,它通过图形界面帮助开发者直观地测试和学习正则表达式。了解并熟练掌握正则表达式在VB.NET中的使用,将极大地提升你在文本处理方面的编程能力。

    易语言正则表达式学习工具

    易语言正则表达式学习工具是一款专为学习和实践正则表达式设计的应用程序,它以易语言作为编程基础,提供了友好的用户界面和丰富的功能,帮助初学者和专业人士更好地理解和掌握正则表达式的核心概念。 正则表达式,...

    正则表达式转换工具

    - 工具支持:利用在线正则表达式测试网站,如Regex101,进行实时调试和学习。 综上所述,"正则表达式转换工具"是处理文本数据的强大辅助,它简化了正则表达式的构造过程,使得非专业人士也能方便地利用正则表达式...

    Python基础入门知识之正则表达式学习 正则表达式30分钟入门教程 共21页.pdf

    为了进一步学习,可以查阅Python官方文档的`re`模块,以及各种正则表达式在线教程和练习网站。 通过这个简短的教程,你应该对Python中的正则表达式有了初步的了解。继续实践和探索,将有助于你更好地掌握这一强大...

Global site tag (gtag.js) - Google Analytics