正则表达式是由普通字符(例如字符 a 到 z)以及特殊字符组成的文字模式。这里的特殊字符也称为元字符,对于不同的元字符,在正则表达式中表达的含义也不相同。
正则表达式的组件可以是单个字符、字符集合、字符范围、字符间的选择或者所有这些组件的任意组合。
普通字符包括没有显式指定为元字符的所有可打印和不可打印字符。这包括所有大写和小写字母、所有数字、所有标点符号和一些其他符号。
字符 | 描述 |
---|---|
a-z A-Z | 匹配小写a-z A-Z |
0-9 | 匹配数字0-9 |
, . ; ’ ! | 匹配标点符号, . ; ’ !等 |
# 匹配字符串中的单个字符a
>>> pattern = r"a"
>>> string = "this is a line!"
>>> re.search(pattern, string)
<re.Match object; span=(8, 9), match='a'>
# 匹配字符串中的单个数字1
>>> pattern = r"1"
>>> string = "1+2=3"
>>> re.search(pattern, string)
<re.Match object; span=(0, 1), match='1'>
# 匹配字符串中的感叹号!
>>> pattern = r"!"
>>> string = "this is a line!"
>>> re.search(pattern, string)
<re.Match object; span=(14, 15), match='!'>
字符 | 描述 |
---|---|
\f | 匹配一个换页符。等价于 \x0c 和 \cL。 |
\n | 匹配一个换行符。等价于 \x0a 和 \cJ。 |
\r | 匹配一个回车符。等价于 \x0d 和 \cM。 |
\t | 匹配一个制表符。等价于 \x09 和 \cI。 |
\v | 匹配一个垂直制表符。等价于 \x0b 和 \cK。 |
# 匹配一个换行符
>>> pattern = r"\n"
>>>> string = "I like python.\nI like python too."
>>> re.search(pattern, string)
<re.Match object; span=(14, 15), match='\n'>
特殊字符在正则表达式中有特殊的含义,如果需要匹配这些特殊字符,则需要在前面添加一个反斜杠\。比如,\\两个反斜杠匹配特殊字符\,\ *匹配特殊字符 *。
字符 | 描述 |
---|---|
\ | 将下一个字符标记为一个特殊字符、或一个原义字符、或一个 向后引用、或一个八进制转义符。 |
. | 匹配任意字符,除了换行符。 |
\b | 匹配一个单词边界,也就是指单词和空格间的位置。 |
\B | 匹配非单词边界。 |
\cx | 匹配由 x 指明的控制字符。 |
\d | 匹配一个数字字符。等价于 [0-9]。 |
\D | 匹配一个非数字字符。等价于 [^0-9]。 |
\s | 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。 |
\S | 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。 |
\w | 匹配字母、数字、下划线。等价于’[A-Za-z0-9_]'。 |
\W | 匹配非字母、数字、下划线。等价于 ‘[^A-Za-z0-9_]’。 |
^ | 匹配输入字符串的开始位置。 |
$ | 匹配输入字符串的结束位置。 |
a|b | 匹配a或b。 |
( ) | 匹配括号内的表达式,也表示一个组。 |
\1…\9 | 匹配第n个分组的内容。 |
[xyz] | 字符集合。匹配所包含的任意一个字符。 |
[^xyz] | 负值字符集合。匹配未包含的任意字符。 |
[a-z] | 字符范围。匹配指定范围内的任意字符。 |
[^a-z] | 负值字符范围。匹配任何不在指定范围内的任意字符。 |
* | 匹配前面的子表达式零次或多次。 |
+ | 匹配前面的子表达式一次或多次。 |
? | 匹配前面的子表达式零次或一次。 |
{n} | n 是一个非负整数。匹配确定的 n 次。 |
{n,} | n 是一个非负整数。至少匹配n 次。 |
{n,m} | m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。 |
(?= re) | 前向肯定界定符。如果所含正则表达式,以 … 表示,在当前位置成功匹配时成功,否则失败。 |
(?<=) | 后向肯定界定符。 |
(?! re) | 前向否定界定符。与肯定界定符相反;当所含表达式不能在字符串当前位置匹配时成功。 |
(?<!) | 后向否定界定符。 |
(?> re) | 匹配的独立模式,省去回溯。 |
特殊字符如何使用的一些例子:
# 匹配所有的数字
>>> string = "123abc456def"
>>> pattern = r"\d+"
>>> re.findall(pattern, string)
['123', '456']
# 匹配组ab出现两次以上的字符串
>>> pattern = r"(ab){2,}"
>>> string = "abcabcababab"
>>> re.search(pattern, string)
<re.Match object; span=(6, 12), match='ababab'>
# 匹配在集合a, b, c中且出现一次以上的字符串
>>> pattern = r"[abc]{1,}"
>>> string = "bcdfghijkl"
>>> re.search(pattern, string)
<re.Match object; span=(0, 2), match='bc'>
>>> pattern = r"[abc]+"
# 用+来代替{1,},结果等价
>>> re.search(pattern, string)
>>> string = "bcdfghijkl"
<re.Match object; span=(0, 2), match='bc'>
界定符使用的例子:
# ?=、?!用法
# 匹配数字前面的字母
>>> pattern = r"[abc]+(?=\d+)"
>>> string = "123abc456def"
>>> re.findall(pattern, string)
['abc']
# 匹配字母后的数字
>>> pattern = r"(?<=abc)[0-9]+"
>>> string = "123abc456def"
>>> re.findall(pattern, string)
['456']
下面来看一个稍微复杂点的例子:
# 邮箱号匹配
>>> pattern = r"\b[\w.%+-]+@[\w.-]+\.[a-zA-Z]{2,6}\b"
>>> string = "python@163.com"
>>> re.search(pattern, string)
<re.Match object; span=(0, 14), match='python@163.com'>