`
carvin
  • 浏览: 212625 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

【转】正则表达式(一):纠结的转义

    博客分类:
  • java
阅读更多

【编者按】正则表达式一直是开发者工具箱中趁手的利器,但很多人对此仍是一知半解。这次InfoQ中文站有幸邀请到来自盛大创新院的余晟,开辟《正则表达式》的专栏,为读者讲解正则表达式的一些技巧和概念。他还是《精通正则表达式》和《技术领导之路》的译者。


用过正则表达式的人都知道,正则表达式中有一类叫做“元字符(meta-character)”的特殊符号,它们并不匹配自身对应的字符,而具有其他的含义。比如脱字符『^』表示“定位到字符串/行的开头”,加号『+』表示“之前的元素重现1次以上。如果需要匹配这些字符本身,需要用反斜线来转义,匹配『^』就应该用\^,匹配『+』就应该用\+。

看起来有点麻烦,但这样的元字符并不多:^$()*+?.[\{|

 

元字符

说明

举例

^

匹配整个字符串的起始位置,或者行的起始位置,如果在字符组内部,则表示排除型(negative)字符组

^Start

$

匹配整个字符串的结束位置,或者行的结束位置

End$

()

分组,提供反向引用(gourp1) \1或多选分支

(ab)+

* + ?

量词,限定之前元素出现的次数

a+ (ab)+

.

默认情况下匹配换行符之外的任意字符,在多行模式下可以匹配换行符

[

字符组的起始符号

[0-9]

\

反斜线用来表示转义序列,或去掉元字符的转义

\1

{

重现限定符的开始

{2, 6}

|

划分多选分支(括号没有出现时,可以想象括号出现在整个表达式最外层)

Tom|Jerry

 

你或许注意到了,这些元字符并不是“对称”出现的,比如与开方括号 [ 对应的闭方括号 ],与开花括号 { 对应的闭花括号 } ,这两个字符是否元字符,需要依据具体正则表达式的情况确定,我们以闭方括号]的情况为例(}的情况与此类似):如果之前能找到与之对应的元字符开方括号[,则]作为元字符出现,否则,作为普通字符出现。

 

字符串 \ 表达式

[ab]]

ab]

a]

ab]

 

另外,因为方括号本身可以表示字符组『[0-9]』,所以在字符组内部的闭方括号在任何情况下都要转义,否则类似『[]]』的正则表达式会出现二义性,造成识别错误。

如果需要匹配方括号内(包括方括号),至少包含一个字符的字符串(比如[text]),所用的正则表达式就应该是:『\[[^\]]+]』。

看明白了吗?『\[』匹配开方括号,然后用一个排除型字符组匹配“除闭方括号 ] 之外的任意字符(注意,在字符组内部,闭方括号 ] 一定需要转义),用『+』表示它至少要出现一次以上,最后用一个『]』匹配闭方括号。

下面用代码来验证,以python为例:

import re #为使用正则表达式,必须首先导入re

>>> re.search('^\[[^\]]+]$', '[abcdefg]') #进行数据验证时,在表达式首尾加上^和$是好习惯

<_sre.SRE_Match object at 0x7ff3bc5e75e0>

>>> re.search('^\[[^\]]+]$', '[]')

>>> 

看来确实没有问题,下面用Java试试。直接调用Java中的string.matches(regex)方法,观察返回的boolean值:

"[]".matches("^\[[^\]]+]$")

但是却出现了编译错误:invalid escape sequence。这是为什么呢?在Python中我们并没有使用raw string(如果使用raw string,就应该用r"^\[[^\]]+]$"),一切正常,可是在Java中为什么会出错呢?

要回答这个问题,就得分清转义的层次和规则。如果你留心观察就会发现,上面我们讲的都是“正则表达式的转义”,比如『\[[^\]]+]』是正确转义的正则表达式。仅仅用做正则表达式,它是绝对没有问题的,但它“不仅仅”是正则表达式,而是“字符串形式给出的正则表达式”——注意到了吗?在表达式两端,各有一个双引号。

回忆一下Java中字符串(String)的规则,其中转义序列(escape sequence)用来表示特殊字符,比如\n表示换行符,\t表示制表符,而\[并不是Java能识别的转义序列,当然要出错了。为了表示“正则表达式中的\[”,我们传递给Pattern.compile()的字符串必须正确表示\[——在字符串中,[ 是不需要转义的,而 \ 是需要转义的,所以在字符串中,应该写做 \\[。

总结一下:

 

字符串的表现层

\\[

字符串的概念层

\[

正则表达式的表现层

\[

正则表达式的概念层

[(非元字符)

 

理解了这一点,就不难理解为什么正则表达式的转义序列在正则表达式中要写两个反斜线了,比如 \+ 要写成 \\+ 。但是 \n 之类的有点特殊,无论你写成 \n 或是 \\n ,结果都是一样,\t之类的情况与此类似。

 

字符串的表现层

\\n

\n

字符串的概念层

\n

换行符

正则表达式的表现层

\[

换行符

正则表达式的概念层

换行符

换行符

 

如果字符串中表示反斜线字符本身(不是用来转义的符号),则需要在正则表达式中写四个反斜线字符。

"\".matches("\\\\"); //true

 

字符串的表现层

\\\\

字符串的概念层

\\

正则表达式的表现层

\\

正则表达式的概念层

\(非元字符)

 

看起来,转义问题似乎就是这样,想明白了也很简单。不过,如果你记忆力比较好,估计会问:为什么在Python中写\[不会报错,而Java中会报错?这确实是个好问题,所以我们把它当成本文的结束。

照道理说,各种语言的转义规则都一样:\n表示换行符,\t表示制表符…… 事实也确实如此,只是Python对字符串的处理更复杂一些:如果一个转义序列不能识别,会直接原样保存到字符串中。也就是说,Python遇到无法识别字符串中的\[,不会报错,而是将它原样“转交”给字符串:

 

字符串的表现层

\[

\\[

字符串的概念层

\[

\[

正则表达式的表现层

\[

\[

正则表达式的概念层

[(非元字符)

[(非元字符)

 

“无法识别的转义序列直接转交字符串”的做法不只Python有,PHP也会这样处理,但是我并不推荐这样使用,因为它往往会令不理解这特性的人困惑,正则表达式对应的字符串中出现\[如何不会报错?\[和\\[为什么竟然是一样的效果?

最好的办法或许还是统一表示法,都写成\\[,既方便与其它语言兼容,也方便大家阅读和理解。

关于作者

余晟,程序员,曾任抓虾网高级顾问,现就职于盛大创新院,感兴趣的方向包括搜索和分布式算法等。翻译爱好者,译有《精通正则表达式》(第三版)和《技术领导之路》,目前正在写作《正则表达式傻瓜书》(暂定名),希望为国内开发同行贡献一本实用的正则表达式教程。

 

原文地址:http://www.infoq.com/cn/news/2011/01/regular-expressions-1

 

分享到:
评论

相关推荐

    正则表达式特殊字符的转义

    正则表达式特殊字符的转义,常用网页特殊字符转义,网络爬虫特殊字符处理

    正则表达式综合练习

    正则表达式(Regular Expression,简称regex)是用于匹配字符串的一种模式,它在IT行业中扮演着重要的角色,尤其是在数据处理、文本分析、爬虫技术等领域。正则表达式通过使用预定义的字符集和特殊符号,可以高效地...

    正则表达式转换工具

    - 字符转义:在正则表达式中,特殊字符需要通过反斜杠`\`进行转义,如`\.`表示匹配实际的点号,而不是任何字符。 - 常规字符到元字符的转换:例如,将`*`转换为`\*`,避免其被解释为量词。 - 正则表达式模式构建...

    正则表达式必知必会v_1.0.pdf

    正则表达式是一种强大的文本处理工具,广泛应用于各个领域。下面是对正则表达式的详细解释: 正则表达式的用途 正则表达式主要用于处理文本,提供了两大主要功能:查找和替换。查找功能允许用户根据不同的规则来...

    从零开始学习正则表达式

    正则表达式语法(05): 边界 正则表达式语法(06): 贪婪匹配与非贪婪匹配 正则表达式语法(07): 匹配转义字符 正则表达式语法(08): 引用子表达式 - 也叫反向正则表达式语法(09): 临界匹配 - 也叫"预搜索"正则表达式语法...

    java正则表达式.zip

    Pattern类是Java正则表达式的起点,它将一个正则表达式编译成一个模式对象。这个编译过程可以优化后续的匹配操作。例如,创建Pattern对象的代码如下: ```java Pattern pattern = Pattern.compile("正则表达式"); `...

    Lucene 使用正则表达式

    正则表达式是一种强大的文本模式匹配工具,广泛应用于字符串搜索和替换等场景。在Lucene中,可以通过`regexQuery`来利用正则表达式进行复杂条件的匹配,从而实现更精确的搜索需求。 #### regexQuery详解 `regexQuery`...

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

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

    java正则表达式匹配工具

    Java正则表达式匹配工具是IT领域中一种强大的文本处理工具,它利用正则表达式(Regular Expression)的规则来查找、替换或者提取文本中的特定模式。正则表达式是一种特殊的字符序列,能够帮助程序员或者用户高效地...

    强大的正则表达式生成工具 C#版

    正则表达式是一种强大的文本处理工具,用于在字符串中进行模式匹配和搜索替换操作。C#作为.NET框架的一部分,提供了全面支持正则表达式的类库,使得开发人员能够方便地利用正则表达式进行复杂的文本处理任务。在这个...

    Oracle中的正则表达式

    正则表达式是一种强大的字符串模式匹配语言,可以用来在字符串中搜索、验证、提取和替换文本。Oracle中的正则表达式函数提供了强大的字符串处理功能,能够大大提高数据库应用程序的效率和可读性。 正则表达式的基本...

    IP地址的正则表达式

    在探讨“IP地址的正则表达式”这一主题时,我们首先需要理解IP地址的基本构成以及正则表达式的原理。IP地址(Internet Protocol Address)是互联网协议为网络上的每个节点分配的一个唯一标识符,用于在网络中定位和...

    关于正则表达式的应用(正则表达式)

    正则表达式是一种强大的文本处理工具,用于在字符串中寻找匹配特定模式的子串。它在编程语言如PHP中有着广泛的应用,包括数据验证、文本提取、搜索与替换等任务。正则表达式通过一系列特殊字符(元字符)和结构来...

    Linux正则表达式.pdf

    正则表达式定义:正则表达式是一种字符串匹配模式,可以用来检查一个串是否含有某种子串、将匹配的子串做替换或者从某个串中取出符合某个条件的子串等。正则表达式是由普通字符(例如字符 a 到 z)以及特殊字符...

    正则表达式验证金额格式

    在IT行业中,正则表达式(Regular Expression)是一种强大的文本处理工具,用于匹配、查找、替换等操作。在本场景中,我们关注的是如何使用正则表达式来验证金额格式。金额格式通常要求精确到小数点后两位,并且可能...

    qt正则表达式测试工具

    这个"qt正则表达式测试工具"显然是一个帮助开发者验证和调试正则表达式的实用程序。 正则表达式是一种特殊的文本字符串,用于描述复杂或重复的文本模式。它们在搜索、替换、数据提取等任务中非常有用。在Qt中,...

    深入浅出之正则表达式(一)

    正则表达式是一种强大的文本处理工具,用于匹配、查找、替换和分析字符串。在深入学习正则表达式之前,我们需要了解其基本概念和工作原理。 1. **什么是正则表达式** 正则表达式(Regular Expression,简称Regex)...

    VB正则表达式简介

    正则表达式是用来描述一个字符串模式的表达式,可以用来测试字符串是否与某个模式匹配,替换文本,根据模式匹配从字符串中提取一个子字符串等。 正则表达式的历史可以追溯到20世纪50年代, Warriors McCulloch 和 ...

    易语言正则表达式匹配中文

    这个命令接受两个参数:一个是待检测的字符串,另一个是正则表达式模式。 对于匹配中文,我们需要了解中文字符的编码。在Unicode编码中,中文字符通常位于`U+4E00`到`U+9FFF`之间,也包括一些扩展区的汉字。因此,...

    JAVA正则表达式大全

    在IT领域,正则表达式(Regular Expression,简称regex)是一种强大的文本处理工具,它用于匹配、查找、替换和分析字符串。在Java编程语言中,正则表达式被广泛应用于数据验证、文本提取和字符串操作。以下是对这些...

Global site tag (gtag.js) - Google Analytics