A. java中什么是正则表达式
正则表达式 就是将一个类型的数据 按照一定方式 写成正则表达式的形式 这样可以辨别数据是否符合这一类型的数据 比如我们的身份证号码 就是有一定的规则的 这样我们写一个 正则表达式 和别人输入的身份证号码 比对 如果符合这个正则表达式的规则 就是身份证号码
B. 正则表达式
如果你曾经用过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的表示形式,所以我们要在每个“\”前面加上一个“\”以免出现编译错误
回答者
C. 什么叫“正则表达式”
如果你曾经用过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的表示形式,所以我们要在每个“\”前面加上一个“\”以免出现编译错误
D. 正则表达式是什么
正则表达式(英文:Regular Expression),在计算机科学中,是指一个用来描述或者匹配一系列符合某个句法规则的字符串的单个字符串。在很多文本编辑器或其他工具里,正则表达式通常被用来检索和/或替换那些符合某个模式的文本内容。许多程序设计语言都支持利用正则表达式进行字符串操作。例如,在Perl中就内建了一个功能强大的正则表达式引擎。正则表达式这个概念最初是由Unix中的工具软件(例如sed和grep)普及开的。“正则表达式”通常缩写成“regex”,单数有regexp、regex,复数有regexps、regexes、regexen。
基本概念 一个正则表达式通常被称为一个模式 (pattern),为用来描述或者匹配一系列符合某个句法规则的字符串。例如:Handel、H�0�1ndel 和 Haendel 这三个字符串,都可以由 "H(a|�0�1|ae)ndel" 这个模式来描述。大部分正则表达式的形式都有如下的结构:替换 | 竖直分隔符代表替换。例如"gray|grey"可以匹配grey或gray。</dd>数量限定 某个字符后的数量限定符用来限定前面这个字符允许出现的个数。最常见的数量限定符包括“+”,“?”和“*”(不加数量限定则代表出现一次且仅出现一次):+ 加号代表前面的字符必须至少出现一次。(1次,或多次)。例如,"goo+gle"可以匹配google,gooogle,goooogle等;</dd>? 问号代表前面的字符最多只可以出现一次。(0次,或1次)。例如,"colou?r"可以匹配colour或者color;</dd>* 星号代表前面的字符可以不出现,也可以出现一次或者多次。(0次,或1次,或多次)。例如,"0*42"可以匹配42,042,0042,00042等。</dd>匹配 圆括号可以用来定义操作符的范围和优先度。例如,"gr(a|e)y"等价于"gray|grey","(grand)?father"匹配father和grandfather。上述这些构造子都可以自由组合,因此,"H(ae?|�0�1)ndel"和"H(a|ae|�0�1)ndel"是相同的。精确的语法可能因不同的工具或程序而异。历史 最初的正则表达式出现于理论计算机科学的自动控制理论和形式语言理论中。在这些领域中有对计算(自动控制)的模型和对形式语言描述与分类的研究。1940年代,Warren McCulloch与Walter Pitts将神经系统中的神经元描述成小而简单的自动控制元。在1950年代,数学家斯蒂芬·科尔·克莱尼利用称之为正则集合的数学符号来描述此模型。肯·汤普逊将此符号系统引入编辑器QED,然后是Unix上的编辑器ed,并最终引入grep。自此,正则表达式被广泛地使用于各种Unix或者类似Unix的工具,例如Perl。Perl正则表达式源自于Henry Spencer写的regex,它已经演化成了pcre(Perl兼容正则表达式Perl Compatible Regular Expressions),一个由Philip Hazel开发的,为很多现代工具所使用的库。各计算机语言之间的正则表达式的整合目前开展的很差。未来的Perl6的子项目Apocalypse的设计中已考虑到了这点。形式语言理论 正则表达式可以用形式语言理论的方式来表达。正则表达式由常量和算子组成,它们分别指示字符串的集合和在这些集合上的运算。给定有限字母表 Σ 定义了下列常量:(“空集”) �6�1 指示集合 �6�1 (“空串”) ε 指示集合 {ε} (“文字字符”) 在 Σ 中的 a 指示集合 {a} 定义了下列运算:(“串接”) RS 指示集合 { αβ | α ∈ R ∧ β ∈ S }。例如 {"ab"|"c"}{"d"|"ef"} = {"abd", "abef", "cd", "cef"}。 (“选择”) R|S 指示 R 和 S 的并集。 (“Kleene星号”) R* 指示包含 ε 并且闭合在字符串串接下的 R 的最小超集。这是可以通过 R 中的零或多个字符串的串接得到所有字符串的集合。例如,{"ab", "c"}* = {ε, "ab", "c", "abab", "abc", "cab", "cc", "ababab", ... }。 上述常量和算子形成了克莱尼代数。很多课本使用对选择使用符号 ∪, + 或 ∨ 替代竖杠。为了避免括号,假定 Kleene 星号有最高优先级,接着是串接,接着是并集。如果没有歧义则可以省略括号。例如,(ab)c 可以写为 abc 而 a|(b(c*)) 可以写为 a|bc*。例子:a|b* 指示 {ε, a, b, bb, bbb, ...}。 (a|b)* 指示由包括空串、任意数目个 a 和 b 字符组成的所有字符串的集合。 ab*(c|ε) 指示开始于一个 a 接着零或多个 b 和最终可选的一个 c 的字符串的集合。 正则表达式的形式定义故意非常精简,避免定义多余的量词 ? 和 +,它们可以被表达为: a+ = aa* 和 a? = (a|ε)。有时增加补算子 ~ ;~R 指示在 Σ* 上的不在 R 中的所有字符串的集合。补算子是多余的,因为它使用其他算子来表达(尽管计算这种表示的过程是复杂的,而结果可能指数性的增大)。这种意义上的正则表达式可以表达正则语言,精确的是可被有限状态自动机接受的语言类。但是在简洁性上有重要区别。某类正则语言只能用大小指数增长的自动机来描述,而要求的正则表达式的长度只线性的增长。正则表达式对应于乔姆斯基层级的类型-3文法。在另一方面,在正则表达式和不导致这种大小上的爆炸的非确定有限状态自动机(NFA)之间有简单的映射;为此 NFA 经常被用作正则表达式的替代表示。我们还要在这种形式化中研究表达力。如下面例子所展示的,不同的正则表达式可以表达同样的语言: 这种形式化中存在着冗余。有可能对两个给定正则表达式写一个算法来判定它们所描述的语言是否本质上相等,简约每个表达式到极小确定有限自动机,确定它们是否同构(等价)。这种冗余可以消减到什么程度? 我们可以找到仍有完全表达力的正则表达式的有趣的子集吗? Kleene 星号和并集明显是需要的,但是我们或许可以限制它们的使用。这提出了一个令人惊奇的困难问题。因为正则表达式如此简单,没有办法在语法上把它重写成某种规 范形式。过去公理化的缺乏导致了星号高度问题。最近 Dexter Kozen 用克莱尼代数公理化了正则表达式。很多现实世界的“正则表达式”引擎实现了不能用正则表达式代数表达的特征。表达式全集 正则表达式有多种不同的风格。下表是在PCRE中元字符及其在正则表达式上下文中的行为的一个完整列表:字符描述\将下一个字符标记为一个特殊字符、或一个原义字符、或一个向后引用、或一个八进制转义符。例如,“n”匹配字符“n”。“\n”匹配一个换行符。序列“\\”匹配“\”而“\(”则匹配“(”。^匹配输入字符串的开始位置。如果设置了RegExp对象的Multiline属性,^也匹配“\n”或“\r”之后的位置。$匹配输入字符串的结束位置。如果设置了RegExp对象的Multiline属性,$也匹配“\n”或“\r”之前的位置。*匹配前面的子表达式零次或多次。例如,zo*能匹配“z”以及“zoo”。*等价于{0,}。+匹配前面的子表达式一次或多次。例如,“zo+”能匹配“zo”以及“zoo”,但不能匹配“z”。+等价于{1,}。?匹配前面的子表达式零次或一次。例如,“do(es)?”可以匹配“do”或“does”中的“do”。?等价于{0,1}。{n}n是一个非负整数。匹配确定的n次。例如,“o{2}”不能匹配“Bob”中的“o”,但是能匹配“food”中的两个o。{n,}n是一个非负整数。至少匹配n次。例如,“o{2,}”不能匹配“Bob”中的“o”,但能匹配“foooood”中的所有o。“o{1,}”等价于“o+”。“o{0,}”则等价于“o*”。{n,m}m和n均为非负整数,其中n<=m。最少匹配n次且最多匹配m次。例如,“o{1,3}”将匹配“fooooood”中的前三个o。“o{0,1}”等价于“o?”。请注意在逗号和两个数之间不能有空格。?当该字符紧跟在任何一个其他限制符(*,+,?,{n},{n,},{n,m})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串“oooo”,“o+?”将匹配单个“o”,而“o+”将匹配所有“o”。.匹配除“\n”之外的任何单个字符。要匹配包括“\n”在内的任何字符,请使用像“[.\n]”的模式。(pattern)匹配pattern并获取这一匹配。所获取的匹配可以从产生的Matches集合得到,在VBScript中使用SubMatches集合,在JScript中则使用$0…$9属性。要匹配圆括号字符,请使用“\(”或“\)”。(?:pattern)匹配pattern但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用“或”字符(|)来组合一个模式的各个部分是很有用。例如,“instr(?:y|ies)就是一个比”instry|instries'更简略的表达式。(?=pattern)正向预查,在任何匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如, “Windows(?=95|98|NT|2000)”能匹配“Windows2000”中的“Windows”,但不能匹配“Windows3.1”中 的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。(?!pattern)负向预查,在任何不匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如 “Windows(?!95|98|NT|2000)”能匹配“Windows3.1”中的“Windows”,但不能匹配“Windows2000”中 的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始x|y匹配x或y。例如,“z|food”能匹配“z”或“food”。“(z|f)ood”则匹配“zood”或“food”。[xyz]字符集合。匹配所包含的任意一个字符。例如,“[abc]”可以匹配“plain”中的“a”。[^xyz]负值字符集合。匹配未包含的任意字符。例如,“[^abc]”可以匹配“plain”中的“p”。[a-z]字符范围。匹配指定范围内的任意字符。例如,“[a-z]”可以匹配“a”到“z”范围内的任意小写字母字符。[^a-z]负值字符范围。匹配任何不在指定范围内的任意字符。例如,“[^a-z]”可以匹配任何不在“a”到“z”范围内的任意字符。\b匹配一个单词边界,也就是指单词和空格间的位置。例如,“er\b”可以匹配“never”中的“er”,但不能匹配“verb”中的“er”。\B匹配非单词边界。“er\B”能匹配“verb”中的“er”,但不能匹配“never”中的“er”。\cx匹配由x指明的控制字符。例如,\cM匹配一个Control-M或回车符。x的值必须为A-Z或a-z之一。否则,将c视为一个原义的“c”字符。\d匹配一个数字字符。等价于[0-9]。\D匹配一个非数字字符。等价于[^0-9]。\f匹配一个换页符。等价于\x0c和\cL。\n匹配一个换行符。等价于\x0a和\cJ。\r匹配一个回车符。等价于\x0d和\cM。\s匹配任何空白字符,包括空格、制表符、换页符等等。等价于[\f\n\r\t\v]。\S匹配任何非空白字符。等价于[^\f\n\r\t\v]。\t匹配一个制表符。等价于\x09和\cI。\v匹配一个垂直制表符。等价于\x0b和\cK。\w匹配包括下划线的任何单词字符。等价于“[A-Za-z0-9_]”。\W匹配任何非单词字符。等价于“[^A-Za-z0-9_]”。\xn匹配n,其中n为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,“\x41”匹配“A”。“\x041”则等价于“\x04”&“1”。正则表达式中可以使用ASCII编码。.\num匹配num,其中num是一个正整数。对所获取的匹配的引用。例如,“(.)\1”匹配两个连续的相同字符。\n标识一个八进制转义值或一个向后引用。如果\n之前至少n个获取的子表达式,则n为向后引用。否则,如果n为八进制数字(0-7),则n为一个八进制转义值。\nm标识一个八进制转义值或一个向后引用。如果\nm之前至少有nm个获得子表达式,则nm为向后引用。如果\nm之前至少有n个获取,则n为一个后跟文字m的向后引用。如果前面的条件都不满足,若n和m均为八进制数字(0-7),则\nm将匹配八进制转义值nm。\nml如果n为八进制数字(0-3),且m和l均为八进制数字(0-7),则匹配八进制转义值nml。\un匹配n,其中n是一个用四个十六进制数字表示的Unicode字符。例如,\u00A9匹配版权符号(�0�8)。范例 以下以PHP的语法所写的范例验证字串是否只含数字与英文, 字串长度并在4~16个字符之间 <?php
$str = 'a1234';
if (preg_match("^[a-zA-Z0-9]{4,16}$", $str)) {
echo "验证成功";
} else {
echo "验证失败";
}
?> 简易的台湾身份证字号验证 <?php
$str = 'a1234';
if (preg_match("^[A-Z]{1}[1-2]{1}[0-9]{8}$", $str)) {
echo "验证成功";
} else {
echo "验证失败";
}
?>
E. 简单说下什么是正则表达式
正则表达式被作为用来描述其称之为“正则集的代数”的一种表达式,因而采用了“正则表达式”这个术语。
简单的说,就是用一个只有“正确”的值,去对比。然后做到其它效果。
===============
以下摘自《网络》
在计算机科学中,是指一个用来描述或者匹配一系列符合某个句法规则的字符串的单个字符串。在很多文本编辑器或其他工具里,正则表达式通常被用来检索和/或替换那些符合某个模式的文本内容。许多程序设计语言都支持利用正则表达式进行字符串操作。例如,在Perl中就内建了一个功能强大的正则表达式引擎。正则表达式这个概念最初是由Unix中的工具软件(例如sed和grep)普及开的。正则表达式通常缩写成“regex”,单数有regexp、regex,复数有regexps、regexes、regexen。
F. 正则表达式概述 什么是正则表达式
正则表达式概述
正则表达式在程序设计语言中存在着广泛的应用,特别是用来处理字符串。如匹配字符串、查找字符串、替换字符串等。可以说,正则表达式是一段文本或一个公式,它是用来描述用某种模式去匹配一类字符串的公式,并且该公式具有一定的模式。
本小节将介绍正则表达式的基本概念、第一个正则表达式,以及测试正则表达式的工具Code Architects Regex Tester。
什么是正则表达式
正则表达式(Regular
Expression)起源于人类神经系统的早期研究。神经生理学家Warren McCulloch和Walter
Pitts研究出一种使用数学方式描述神经网络的方法。1956年,数学家Stephen
Kleene发表了一篇标题为“神经网事件的表示法”的论文,并在该论文中引入了“正则表达式”这一个概念。该论文称正则表达式是:“正则集的代数”的表达式。因此,采用“正则表达式”这个术语。正则表达式的定义存在多种说法,具体如下:
正则表达式就是用某种模式去匹配一类字符串的公式,主要用来描述字符串匹配的工具。
正则表达式描述了一种字符串匹配的模式。它可以用来检查字符串是否含有某种子串、将匹配的子串做替换或者从某个串中取出符合某个条件的子串等。
正则表达式是由普通字符(如字符a到z)以及特殊字符(称为元字符)组成的文字模式。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配。
正则表达式就是用于描述某些规则的工具。这些规则经常用于处理字符串中的查找或替换字符串。换句话说,正则表达式就是记录文本规则的代码。
正则表达式就是用一个“字符串”来描述一个特征,然后去验证另一个“字符串”是否符合这个特征。
学过《编译原理》的读者可能知道不确定有限自动机(Non-deterministic
finite automaton,简称NFA)和确定有限自动机(Deterministic finite
automaton,简称DFA)。其实,正则表达式是一个不确定有限自动机。NFA和DFA的最大区别在于它们的状态转换函数。NFA可以对同一个字符串产生多种理解方式,而DFA则只有唯一的一种理解方式。也正因为如此,NFA在匹配过程中可能会回溯,NFA的效率一般要低于DFA。因此,在书写正则表达式时尽量减少回溯来提高正则表达式的效率。
如果你使用过Windows或DOS下用于文件查找的通配符*和?,那么你不难理解正则表达式。如果你需要查找所有Word文档,那么可能使用表达式*.doc。其中,字符*是一个通配符,它可以代表任意字符串。正则表达式和通配符具有相似性,它也可以使用一些字符(如字符.)表示任意字符。然而,它比通配符更具有精确性。
在正则表达式中,匹配是最常用的一个词语,它描述了正则表达式动作结果。给定一段文本或字符串,使用正则表达式从文本或字符串中查找出符合正则表达式的字符串。有可能文本或字符存在不止一个部分满足给定的正则表达式,这时每一个这样的部分被称为一个匹配。其中,匹配存在下面3种类型:
形容词性的匹配,即一个字符串匹配一个正则表达式。
动词性的匹配,即在文本或字符串里匹配正则表达式。
名词性的匹配,即字符串中满足给定的正则表达式的一部分。
正则表达式的应用非常广泛,特别是在字符串处理方面。目前来说,正则表达式已经在很多软件中得到广泛了应用,如Linux、Unix、HP等操作系统,C#、PHP、Java等程序开发环境,以及很多的应用软件中,都可以看到正则表达式的这样或那样的应用。正则表达式常见的应用如下:
验证字符串,即验证给定的字符串或子字符串是否符合指定特征,譬如验证是否是合法的邮件地址、验证是否为合法的HTTP地址等。
查找字符串,从给定的文本中查找符合指定特征的字符串,比查找固定字符串更加灵活方便。
替换字符串,即把给定的字符串中的符合指定特征的子字符串替换为其他字符串,比普通的替换更强大。
提取字符串,即从给定的字符串中提取符合指定特征的子字符串。
G. .net 中的正则表达式如何理解:
正则表达式不容易理解,即使是已经工作的程序员对正则也是很头疼的,建议你参考一下正则表达式的一些入门教程,就算不会写,先做到能明白其中的字符含义。
正则中的字符只有严格的规定,只有你熟记这些规定才能应用自如,这些在网上大多找得到,复制到这里不过是无谓浪费你的阅读时间。
http://www.regexlab.com/zh/regref.htm
可以看一下这份正则表达式参考文档,对理解以上正则有一定帮助。
H. java正则表达式是什么
在程序开发中,难免会遇到需要匹配、查找、替换、判断字符串的情况发生,而这些情况有时又比较复杂,如果用纯编码方式解决,往往会浪费程序员的时间及精力。因此,学习及使用正则表达式,便成了解决这一矛盾的主要手段。
正则表达式是一种可以用于模式匹配和替换的规范,一个正则表达式就是由普通的字符(例如字符a到z)以及特殊字符(元字符)组成的文字模式,它 用以描述在查找文字主体时待匹配的一个或多个字符串。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配。
(8)程序员的正则表达式原理扩展阅读:
正则表达式的特点是:
1、灵活性、逻辑性和功能性非常强;
2、可以迅速地用极简单的方式达到字符串的复杂控制。
3、对于刚接触的人来说,比较晦涩难懂。
由于正则表达式主要应用对象是文本,因此它在各种文本编辑器场合都有应用,小到着名编辑器EditPlus,大到Microsoft Word、Visual Studio等大型编辑器,都可以使用正则表达式来处理文本内容。