本文适合初学者,和没有系统学习正则表达式的人阅读,帮助您解决绝大部分正则表达式是的问题。
包括名词和量词的方法轻松理解的方法;获取匹配和非获取匹配的区别;匹配结果存储的方式;前缀后缀匹配;正则表达式中或和与操作等。
1 正则表达式主要两种类型
1.1 名词:代表是什么,用[]表示,如:[a]
代表a字母,[ab]
代表a或b字母,[0-9]
代表0到9,还有一些简写形式,如:\w
代表[a-zA-Z0-9_]
字母数字或者下划线,\d
代表[0-9]
数字,\D
代表\[^0-9\]
非数字,\s
代表[ \f\n\r\t\v]
可见字符,.
代表任意字符。
1.2 量词:代表个数,{n}
代表有n个,{n,m}
代表有n到m个,{n,}
代表>=n个,{,m}
代表<=m个,还有一些简写形式,如:*
代表{0,}
任意个,+
代表{1,}
至少有一个,?
代表{0,1}
代表最多有一个。
1.3 正则表达式翻译方法:[abc]{n,m} => 有n到m个'a'或'b'或'c'
,如果名词只有一个可以省略[],如果只需要一个可以省略量词。
import re
def printRes(res):
if res:
print(res.group())
else:
print("No match")
def main():
str = "abc123123qwe"
reg = re.compile(r"123") # 一个(123)
# search是匹配首个结果
result = reg.search(str)
printRes(result) # 123
reg = re.compile(r"123{2}") # 一个1一个2两个3
# search是匹配首个结果
result = reg.search(str)
printRes(result) # No match
reg = re.compile(r"(123){2}") # 两个(123)
# search是匹配首个结果
result = reg.search(str)
printRes(result) # 123123
reg = re.compile(r"\d{2,3}[a-z]{1,2}") #两到三个数字,一到两个小写字母
# search是匹配首个结果
result = reg.search(str)
printRes(result) # 123qw
if __name__ == '__main__':
main()
正则表达式中|
符号优先级最低。
python中 .
代表非\n以外的任意字符,compile时加上re.DOTALL
标签后才代表任意字符。
2 匹配结果:以python为例
import re
def main():
str = "The cat is red and the dog is yellow"
reg = re.compile(r"[t|T]he (cat|dog) is (\S+)") #\S 可见字符
# search是匹配首个结果
print(reg.search(str).group()) # 匹配的整个字符串 The cat is red
print(reg.search(str).group(1)) # 字符串中第一个()的内容 cat
print(reg.search(str).group(2)) # 字符串中第二个()的内容 red
# findall是匹配所有的结果
print(reg.findall(str)) # [('cat', 'red'), ('dog', 'yellow')]
reg = re.compile(r"[t|T]he \S+ is \S+")
# search是匹配首个结果
print(reg.search(str).group()) # 匹配的整个字符串 The cat is red
# findall是匹配所有的结果
print(reg.findall(str)) # ['The cat is red', 'the dog is yellow']
reg = re.compile(r"[t|T]he (?:cat|dog) is \S+") # |的优先级最低
# search是匹配首个结果
print(reg.search(str).group()) # 匹配的整个字符串 The cat is red
# findall是匹配所有的结果
print(reg.findall(str)) # ['The cat is red', 'the dog is yellow']
if __name__ == '__main__':
main()
()会单独放入到结果,而(?:)不会放入其中。
3 还有几种辅助类型
3.1 抽象位置:不占字符,只是显示位置,如:^表示开始,$表示结尾,\b表示单词边界(是\w\W的边界),\B非单词边界。
import re
def printRes(res):
if res:
print(res.group())
else:
print("No match")
def main():
str = "this is windows7!"
reg = re.compile(r'windows') # 只要含有windows就可以匹配成功。
# search是匹配首个结果
result = reg.search(str)
printRes(result) # windows
reg = re.compile(r'^windows$') # w前必须是字符串开头,s后面必须是字符串结尾。
# search是匹配首个结果
result = reg.search(str)
printRes(result) # No match
reg = re.compile(r'\bwindows\b')# w前面必须是\W,s后面必须是\W。
# search是匹配首个结果
result = reg.search(str)
printRes(result) # No match
if __name__ == '__main__':
main()
注意:在正确性匹配时一定要加上^$符号,否则很容器出现漏洞。
3.2 非获取匹配: 只匹配内容,却不消耗字符,接下来还可以继续匹配。
import re
def printRes(res):
if res:
print(res.group())
else:
print("No match")
def main():
str = "this is windows7!"
reg = re.compile(r'windows(?=7)') # 后缀
# search是匹配首个结果
result = reg.search(str)
printRes(result) # windows
reg = re.compile(r'windows(?=8)') # 后缀
# search是匹配首个结果
result = reg.search(str)
printRes(result) # No match
reg = re.compile(r'windows(?!8)') # 非后缀
# search是匹配首个结果
result = reg.search(str)
printRes(result) # windows
reg = re.compile(r'(?<=is )windows')# 前缀
# search是匹配首个结果
result = reg.search(str)
printRes(result) # windows
reg = re.compile(r'(?<=are )windows')# 前缀
# search是匹配首个结果
result = reg.search(str)
printRes(result) # No match
reg = re.compile(r'(?<!is )windows')# 非前缀
# search是匹配首个结果
result = reg.search(str)
printRes(result) # No match
# 接下来解释什么叫做非获取
str = "989898"
# 正常查找98的匹配结果
reg = re.compile(r'98')
# findall是匹配所有的结果
print(reg.findall(str)) # ['98', '98', '98']
# 匹配以98为前缀的98
reg = re.compile(r'(?:98)(98)')
# findall是匹配所有的结果
print(reg.findall(str)) # ['98'] ?:需要获取(独占)字符串,下一次匹配无法使用。
# 匹配以98为前缀的98
reg = re.compile(r'(?<=98)(98)')
# findall是匹配所有的结果
print(reg.findall(str)) # ['98', '98'] 中间的98已经被第一次获取,但是非获取型匹配可以继续使用。
# 正则表达式中有|操作符,但是没有&操作符。非获取型可以实现&
# 下面实现字符串中,即有数字也有字母且不能是特殊字符的匹配。
reg = re.compile(r'^(?=.*\d)(?=.*[a-zA-Z])\w*$')
res = reg.search('123')
printRes(res) # No match
res = reg.search('abc')
printRes(res) # No match
res = reg.search('1bc')
printRes(res) # 1bc
if __name__ == '__main__':
main()
4 两种模式:贪婪模式和非贪婪模式
贪婪模式尽量多匹配,非贪婪模式尽量少匹配。
import re
def printRes(res):
if res:
print(res.group())
else:
print("No match")
def main():
str = "<h1 class='red'>Hello world!</h1>"
# 默认是贪婪模式
reg = re.compile(r'<h1.*>')
# search是匹配首个结果
result = reg.search(str)
printRes(result) # <h1 class='red'>Hello world!</h1>
# 非贪婪模式
reg = re.compile(r'<h1.*?>')
# search是匹配首个结果
result = reg.search(str)
printRes(result) # <h1 class='red'>
if __name__ == '__main__':
main()