(转)
大家好:
正则表达式是一个比较古老的技术了,现在应用却越来越广泛,尤其在 Web 前端的开发中,处理的对象主要是字符串格式,在前端库中,你可以看到各种正则表达式,如果不认识的话,还是比较痛苦的。特别是现在的高级编辑器,都提供了使用正则表达式的搜索功能,会写正则表达式,会让你的生活更美好。
传说正则表达式是一个从研究神经病学转过来的程序员研发的技术,我感觉很像中国传统道士画出的驱鬼符,看不懂的时候,特别神秘,懂了的话,就会符到妖除。
这一次,我们先看正则表达式的两个基本概念。
首先,正则表达式是关于文本的技术,可以帮助我们在文本中搜索特定的内容。
比如,在 Visual Studio 的文本编辑器中,就可以直接使用正则表达式进行高级搜索。下面的练习,你可以直接在 Visual Studio 的文本编辑器中完成。
第二部分
第一个概念 元字符
在搜索文本的时候,我们必须先描述一下搜索的目标,比如记事本就支持将搜索的内容完全写出来,比如搜索 hello 这个词,在正则表达式中,每个搜索的目标是使用多个元字符来表示的,比如,在 ‘hello’ 这个词中,就有 5 个字面的元字符。这些字符直接表示我们搜索的目标,是直接写出来的,我们一般称为字面量。
能够逐个字符直接描述出我们的搜索目标当然好了,但是,很多时候,我们很难直接写出来,比如只记得 hello 的前两个字母了,我们要找这个词怎么办?
可以使用通配符来描述,每个通配符可以表示一个字符,在正则表达式中,英文的圆点 (.) 表示任意一个除了换行符之外的字符,如果我们知道这个单词共有 5 个字符,就可以写成 he… 了。如果要表示的字符就是圆点怎么办呢?在正则表达式中,需要使用反斜杠进行转义,所有,写出来就是 . 了,因此,正则表达式应该是 he... 。
圆点 (.) 可以匹配除了换行的任意字符,那么,he*** 也可以被匹配,而我们的目标必须是字符,还可以使用更为特殊的元字符来严格限制一下,w 可以匹配任何一个字母、数字或者下划线。所以,我们可以写成 hewww, 注意,一个元字符只能匹配一个字符,所以要写三遍。这样 he*** 就不会过来捣乱了。
常用的元字符有 7 个
. |
匹配除换行符以外的任意字符 |
w |
匹配字母或数字或下划线或汉字 |
s |
匹配任意的空白符 |
d |
匹配数字 |
W |
匹配任意不是字母,数字,下划线,汉字的字符 |
S |
匹配任意不是空白符的字符 |
D |
匹配任意非数字的字符 |
看到了,元字符改变大小写,意义正好相反,小写字符表示范围,大写表示不在范围,很好记。
自定义字符范围
但是 he123 还是可以被匹配的,能不能再进一步限制到英文字母呢?当然可以,只不过没有预定义好的元字符了,需要我们自己来描述一下可选的范围。
使用 [] 可以明确指出我们备选的字符,列在中括号中的字符就是备选字符,比如,限制为英文小写字符,可以把小写字符全列出来,[abcdefghijklmnopqrstuvwxyz],这个表达式就可以表示从 a 到 z 之间的任何一个字符,不会出现数字了。
那么,我们的正则表达式可以写成 he[abcdefghijklmnopqrstuvwxyz] [abcdefghijklmnopqrstuvwxyz] [abcdefghijklmnopqrstuvwxyz],你是不是已经晕掉了,我还不够麻烦的。
为了减轻你的负担,在 [] 中允许使用连字符来设置范围,比如 [a-z] 就可以表示刚才的从 a 到 z 的所有小写英文字符了。从 0 到 9 的数字就可以写成 [0-9] 了。注意,写成 [9-0] 可不行,有方向的。
这样,我们可以使用正则表达式 he[a-z][a-z][a-z] 来搜索 he 开头的 5 个字符组成的目标。感觉好一点了吧。
边界字符
要是遇到了 heabcdefg 会发生什么呢?我们还是会匹配上其中的 heabc 的,但这并不是一个 5 个字符组成的单词,所以,我们还需要表示一下,在我们的 5 个元字符之后,不能是其他的普通字符了,应该是类似空格、制表、换行之类的分隔符,或者,进一步说,是遇到了空格、制表、回车之类的符号就完成,但是,我们不需要匹配这个空格、制表、回车符号。
在正则表达式中,我们称之为边界,边界是一个特殊的位置,比如开头,结尾的位置,或者单词开始结束的位置,位置并不是普通意义上的字符。所以,肯定需要用特殊的方式来表示一下了。
常用的位置有 4 个。
匹配单词的开始或结束 |
|
^ |
匹配字符串的开始 |
$ |
匹配字符串的结束 |
B |
匹配不是单词开头或结束的位置 |
就表示单词的边界,比如说逗号 (,) 句号 (.) 空格等等,我们可以重新写成 he[a-z][a-z][a-z],这样就表示一个 5 个字符组成,开头为 he 的单词了。
第二个概念,也是这次的最后一个,数量词
现在,我们的表达式he[a-z][a-z][a-z] 还是比较繁琐,应该简化什么呢?当然是写了三遍的 [a-z] 了,这个单词只有 5 个字符,听说过 i18n 问题吗?国际化的英文单词长度是 18 个字符,连老外都直接写成 i18n 了,要是也写成我们这样的正则,还不累死。数量词就是解决这个问题的。
如果你嫌重复写多编麻烦,可以使用 * ,它表示把紧接着它前面的元字符重复多遍,这个 n 可以从 0 直到 n,如果我们的正则写成 he[a-z]*,它就表示 一个至少有两个字符,以 he 开头的单词了,你看,最少的情况下,可以匹配 he 这个词,healthy 也可以匹配。
如果不想匹配 he 这个词,希望 [a-z] 至少匹配一个字符,可以使用加号 (+),与星号 (*) 的区别是,这个 n 是从 1 到 n 的。
如果只希望匹配 0 次或者 1 次,可以使用问号 (?),这个 n 从 0 到 1。
慢着,说了半天,都不是我们要的,我需要的是重复 3 遍,必须是 3 遍,不能多,也不能少,那你可以使用 {n} ,这个 n 你可以直接设置,现在可以写成 he[a-z]{3}了。是不是很爽了。
还可以指定至少几次,或者重复 n 到 m 次。
常用的数量词 |
|
代码/语法 |
说明 |
* |
重复零次或更多次 |
+ |
重复一次或更多次 |
? |
重复零次或一次 |
{n} |
重复n次 |
{n,} |
重复n次或更多次 |
{n,m} |
重复n到m次 |
总结一下
这里介绍了正则表达式的用途,基本的元字符和数量词用法。
不过这都是非常基本的用法,以后我们慢慢介绍高级用法,如果你着急的话,可以先看一篇文章《正则表达式 30 分钟入门教程》。
对于开发人员来说,还可以安装 RegexBuddy 这个工具,里面集成了学习,创建,测试正则表达式的各种功能,程序员的神器呀。