正则表达式
一,前言:
在《Java编程思想》一书中,作者提到了一句话可以证明,字符串操作是计算机程序设计中最常见的行为,这一点,如果你接触过Python或者Shell这两门语言的话,你也会和我一样对这句话再赞成不过了。而既然提到了字符串操作,就得接触到正则表达式这一神器啦。
正则表达式,是一个用于字符串匹配与搜索的工具,它的语法十分强大而灵活,然而也有点晦涩难懂(我比较愚钝)。
有些人在碰到问题时,就像:“我知道,我可以使用正则表达式。” 现在,他们就有2个问题了--------Jamie “jwz” Zawinski ( 1997.8)
二,两个重要概念:
1.匹配(match):
匹配是指判断一个模式(pattern)能否在字符串起始处全部或者部分地区匹配,python里面用的match(), Java 用的matches()。
2.搜索:
搜索是指在字符串任意部分中搜索匹配的模式(patter),python中的用的search(), Java用的find()
三,特殊符号(元符号):
1. 语法:
正则表达式用一个模式(pattern)来匹配某个字符串,这个模式也是一个字符串,不过这个字符串从左到右地用一些特殊符号来表示所要匹配的对象。
2. 特殊符号:
- 符号
表示法 | 描述 | 示例 |
---|---|---|
literal | 匹配文本字符串的字面值 | foo |
re1|re2 | 匹配模式re1或者re2 | foo| bar |
. | 匹配任意字符[a-zA-Z0-9] | b.b |
^ | 匹配字符串起始部分 | ^oo |
$ | 匹配字符串终止部分 | cpp$ |
* | 匹配0次或者多次前面的模式 | oo* |
+ | 匹配1次或者多次前面出现的模式 | [a-z]+.com |
? | 匹配0次或者1次前面出现的模式 | foo? |
{M}, {M,N} | 匹配前面的模式M次,或者M至N次 | a{1, 3} |
[…], […-…] | 匹配[]中的字符或者字符集 | [a-z],[0-9] |
[^…] | 不匹配[]中的任一字符 | [^a-z] |
(X) | 匹配括号中封闭的模式,并存为子组,可在后面用\i去引用它 | (.f)oo |
X|Y | 逻辑或,匹配X或者Y | f(oo | ee) |
- 字符类
表示法 | 描述 | 示例 |
---|---|---|
\d | 表示十进制数字,等价于[0-9] | data\d?\.txt |
\w | 匹配任何字母与数字,等价于[0-9a-zA-Z] (\W 大写则表示不匹配) | \w+\.cpp |
\s | 匹配任何空白字符(空格,制表符等),等价于[A-Za-z0-9](\S 大写则表示不匹配) | hello\shi |
\b | 匹配任何单词边界(\B与之相反) | \bThe\b(只能匹配单个The单词) |
\N | 匹配第N个子组(上面提到的用()起来的模式) | price:\16 |
\c | 逐字匹配任何特殊字符c,仅按照字符意思来匹配,即防止转义 | \. , \\, \* |
3.量词
量词描述了一个文本吸收输入文本的方式(简单来说就是匹配次数),分类如下
贪婪型 | 勉强型(非贪婪) | 如何匹配 |
---|---|---|
X? | X?? | 一个或零个X |
X* | X*? | 零个或者多个X |
X+ | X+? | 一个或多个X |
X{m,}, X{m,} X{m,n} | X{m,}, X{m,} X{m,n} | m次或者m次以上,或者m到n次 |
- 正则表达式用*, ?, + 来表达匹配次数(非具体的)
- 贪婪模式:即指定尽可能多地在匹配更多的模式,如表达式 “a+b”,可以匹配"aaaab",但是“ab”就匹配不了"aaaab"
- 非贪婪模式:即指定尽可能少地匹配,如在用搜索模式得到
<p> hello world</p>
的标签时(假设我不知标签内字符数量),如果用“<.+>“来搜索,那么我会得到<p> hello world </p>
而不是我们要的标签,为啥呢?因为”.“这个表达式因为"+"而被指定了贪婪模式,它会尽可能多匹配字符,所有”.+“匹配包括第一个”<"和最后一个“>”之间,而要指定非贪婪怎么办呢?在“.+”后面加“?”就可以了,即“<.+?>”,这时便会搜索到标签了
In [1]: test = "<p> hello world </p>"
In [2]: import re
In [3]: pat_1 = re.compile("<.+>")
In [4]: result_1 = pat_1.search(test)
In [5]: result_1
Out[5]: <re.Match object; span=(0, 20), match='<p> hello world </p>'>
In [6]: pat_2 = re.compile("<.+?>")
In [7]: result_2 = pat_2.search(test)
In [8]: result_2
Out[8]: <re.Match object; span=(0, 3), match='<p>'>
4.几个常用的正则表达式
表达式 | 用处 |
---|---|
^[\u4e00-\u9fa5]{0,}$ | 汉字 |
^\w+([-+.]\w+)@\w+([-.]\w+).\w+([-.]\w+)*$ | 邮箱地址 |
[a-zA-z]+://[^\s]* 或 ^http://([\w-]+.)+[\w-]+(/[\w-./?%&=]*)?$ | url地址 |
^\d{15}|\d{18}$ | 身份证 |
^\d{4}-\d{1,2}-\d{1,2} | 日期 |
\d+.\d+.\d+.\d+ | IP地址 |
5.后话
正则表达式不管在python, java,还是C++中都有相应的库,关于这些库的用法以后再说,以上的东西都是一些最基本的,但也是最通用的,学会了以后便会少一个问题。