`
xb583xb
  • 浏览: 9838 次
社区版块
存档分类
最新评论

转余晟老师的正则专栏文章:(一):纠结的转义

 
阅读更多

  【编者按】正则表达式一直是开发者工具箱中趁手的利器,但很多人对此仍是一知半解。这次InfoQ中文站有幸邀请到来自盛大创新院的余晟,开辟《正则表达式》的专栏,为读者讲解正则表达式的一些技巧和概念。他还是《精通正则表达式》和《技术领导之路》的译者。
  用过正则表达式的人都知道,正则表达式中有一类叫做"元字符(meta-character)"的特殊符号,它们并不匹配自身对应的字符,而具有其 他的含义。比如脱字符『^』表示"定位到字符串/行的开头",加号『+』表示"之前的元素重现1次以上。如果需要匹配这些字符本身,需要用反斜线来转义, 匹配『^』就应该用\^,匹配『+』就应该用\+。
  看起来有点麻烦,但这样的元字符并不多:^$()*+?.[\{| 元字符 说明 举例 ^ 匹配整个字符串的起始位置,或者行的起始位置,如果在字符组内部,则表示排除型(negative)字符组 ^Start $ 匹配整个字符串的结束位置,或者行的结束位置 End$ () 分组,提供反向引用(gourp1) \1或多选分支 (ab)+ * + ? 量词,限定之前元素出现的次数 a+ (ab)+ . 默认情况下匹配换行符之外的任意字符,在多行模式下可以匹配换行符   [ 字符组的起始符号 [0-9] \ 反斜线用来表示转义序列,或去掉元字符的转义 \1 { 重现限定符的开始 {2, 6} | 划分多选分支(括号没有出现时,可以想象括号出现在整个表达式最外层) Tom|Jerry 你或许注意到了,这些元字符并不是"对称"出现的,比如与开方括号 [ 对应的闭方括号 ],与开花括号 { 对应的闭花括号 } ,这两个字符是否元字符,需要依据具体正则表达式的情况确定,我们以闭方括号]的情况为例(}的情况与此类似):如果之前能找到与之对应的元字符开方括号 [,则]作为元字符出现,否则,作为普通字符出现。 另外,因为方括号本身可以表示字符组『[0-9]』,所以在字符组内部的闭方括号在任何情况下都要转义,否则类似『[]]』的正则表达式会出现二义性,造成识别错误。
  如果需要匹配方括号内(包括方括号),至少包含一个字符的字符串(比如[text]),所用的正则表达式就应该是:『\[[^\]]+]』。
  看明白了吗?『\[』匹配开方括号,然后用一个排除型字符组匹配"除闭方括号 ] 之外的任意字符(注意,在字符组内部,闭方括号 ] 一定需要转义),用『+』表示它至少要出现一次以上,最后用一个『]』匹配闭方括号。
  下面用代码来验证,以python为例:
  import re #为使用正则表达式,必须首先导入re
  >>> re.search('^\[[^\]]+]$', '[abcdefg]') #进行数据验证时,在表达式首尾加上^和$是好习惯
  
  >>> 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也会这样处理,但是我并不推荐这样使用,因为它往往会令不理解这特性的人困惑,正则表达式对应的字符串中出现\[如何不会报错?\[和\\[为什么竟然是一样的效果?
  最好的办法或许还是统一表示法,都写成\\[,既方便与其它语言兼容,也方便大家阅读和理解。
  关于作者
  余晟,程序员,曾任抓虾网高级顾问,现就职于盛大创新院,感兴趣的方向包括搜索和分布式算法等。翻译爱好者,译有《精通正则表达式》(第三版)和《技术领导之路》,目前正在写作《正则表达式傻瓜书》(暂定名),希望为国内开发同行贡献一本实用的正则表达式教程。
分享到:
评论

相关推荐

    正则表达 转义字符

    正则表达 转义字符正则表达 转义字符正则表达 转义字符正则表达 转义字符正则表达 转义字符

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

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

    从零开始学习正则表达式

    正则表达式语法(01): 关于大小写与中文 正则表达式语法(02): 或者与重复 正则表达式语法(03): 匹配范围 正则表达式语法(04): 常用转义字符与 . 正则表达式语法(05): 边界 正则表达式语法(06): 贪婪匹配与非贪婪匹配 ...

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

    escape-string-regexp - 特殊字符转义正则表达式

    正则表达式基本语法,各类字符的转义

    只能输入由26个大写英文字母组成的字符串:"^[A-Z]+$"。  只能输入由26个小写英文字母组成的字符串:"^[a-z]+$"。  只能输入由数字和26个英文字母组成的字符串:"^[A-Za-z0-9]+$"。  只能输入由数字、26个英文...

    正则表达式-字符转义 .net .xlsx

    正则表达式在。net下的转义符意义 正则表达式是正则表达式引擎尝试匹配输入文本的一种模式。 模式由一个或多个字符文本、运算符或构造组成

    从零开始学习正则表达式.rar

    正则表达式学习基础篇正则表达式语法(01): 关于大小写与中文 正则表达式语法(02): 或者与重复 正则表达式语法(03): 匹配范围 正则表达式语法(04): 常用转义字符与 . 正则表达式语法(05): 边界 正则表达式语法(06): ...

    易语言正则元字符转义工具

    易语言自带正则支持库和VB的不太一样,有些元字符需要转义,否则就会创建失败,为了方便使用,写此工具

    正则表达式C#实现帮助类

    正则表达式是一种用于匹配和操作文本的工具,它基于特定的语法规则。以下是一些常见的正则表达式规则: 1. 字符类(Character classes):字符类用方括号 [ ] 表示,可以匹配其中的任何一个字符。例如,[abc] 表示...

    MySQL的正则表达式

    MySQL的正则表达式

    regexp-escape:在正则表达式中使用的转义字符串

    RegExp.escape返回一个带有转义正则表达式字符的字符串,以便在正则表达式中使用。 用法 var strName = 'Dr. Doogie Howser, M.D.' ; var escName = RegExp . escape ( strName ) ; // Dr\. Doogie Howser, M\.D\. ...

    c#转义字符串中的所有正则特殊字符方法示例

    代码如下:///  /// 转义字符串中所有正则特殊字符 ///  /// ”input”>传入字符串 /// <returns></returns> string FilterString(string input) { input = input.Replace(“\\”, “\\\\”);//先替换“\”,...

    正则表达式语法

    所以,在其他的语言中,一个反斜杠\就足以具有转义的作用,而在正则表达式中则需要有两个反斜杠才能被解析为其他语言中的转义作用。也可以简单的理解在正则表达式中,两个 \ 代表其他语言中的一个 \,这也就是为什么...

    正则表达式

    除此之外正则表达式中有一些特殊的字符,这些字符在正则表达式中有特殊的用途,如前面介绍的反斜线(\),如果需要匹配这些字符,必须首先将这些字符转义,也就是再前面添加一个反斜线(\).正则表达式中的特殊字符: 1)...

    第11.14节 正则表达式转义符和Python转义符相同引发问题的解决办法.rar

    第11.14节 正则表达式转义符和Python转义符相同引发问题的解决办法.rar

    Java正则表达式处理特殊字符转义的方法

    由于正则表达式定了一些特殊字符,而有时候需要对这些特殊字符进行匹配的话就需要进行转义了,下面这篇文章主要给大家介绍了Java正则表达式处理特殊字符转义的方法,需要的朋友可以参考借鉴,下面来一起看看吧。

    正则表达式规则.rar

    正则表达式规则 1.1 普通字符 字母、数字、汉字、下划线、以及后边章节中没有特殊定义的标点符号,都是"普通字符"。表达式中的普通字符,在匹配一个字符串的时候,匹配与之相同的一个字符。 举例1:表达式 "c",...

    正则表达式 特殊字符

    正则表达式需要转义的特殊字符 一定要注意书写规范。

Global site tag (gtag.js) - Google Analytics