Day 19
re模块
正则表达式:由一系列特殊字符拼接而成的表达式/规则,该表达式用于从一个大字符串中匹配出符合规则的子字符串
re常用方法
表达式方法 | 使用方法 |
---|---|
re.findall(pattern, string, flags=0) | 返回字符串中所有不重叠匹配项的列表。如果模式中存在一个或多个捕获组,则返回一个组列表;否则,返回一个列表。如果模式有多个组,这将是一个元组列表(空匹配项包含在结果中) |
re.rearch(pattern, string, flags=0) | 扫描字符串以查找与模式的匹配项,并返回第一个成功的匹配;如果未找到匹配项,则返回None。 |
re.compile(pattern, flags=0) | 编译一个正则表达式模式,返回一个Pattern对象 |
re.sub(pattern, repl, string, count=0, flags=0) | 替换字符串中每一个匹配的字串,并返回替换后的结果 |
字符 | 功能 |
---|---|
. | 匹配任意1个字符(除了\n) |
[ ] | 匹配[ ]中列举的字符 |
\d | 匹配数字,即0-9 |
\D | 匹配非数字,即不是数字 |
\s | 匹配空白,即 空格,tab键 |
\S | 匹配非空白 |
\w | 匹配单词字符,即a-z、A-Z、0-9、_ |
\W | 匹配非单词字符 |
* | 匹配前一个字符出现0次或者无限次,即可有可无 |
+ | 匹配前一个字符出现1次或者无限次,即至少有1次 |
{m} | 匹配前一个字符出现m次 |
{m,n} | 匹配前一个字符出现从m到n次 |
| | 匹配左右任意一个表达式 |
(ab) | 将括号中字符作为一个分组 |
^ | 匹配字符串开头 |
$ | 匹配字符串结尾 |
\W 和 \w
# \w # 匹配单词字符,即a-z、A-Z、0-9、_
print(re.findall("\w\w", "我是你爸爸把,asda____9sd8a90s)(*)(*&*^"))
--------------------------------
>>> ['我是', '你爸', '爸把', 'as', 'da', '__', '__', '9s', 'd8', 'a9', '0s']
# \W # 匹配非单词字符
print(re.findall("\W\W", "我是你爸爸把,asda____9sd8a90s)(*)(*&*^"))
-------------------------------
>>> [')(', '*)', '(*', '&*']
\S 和 \s
# \s 匹配空白,即 空格,tab键
print(re.findall("\s", """我是
你 爸爸\n把,as\tda____9sd\r8\fa9\t0s)(*)(*&*^"""))
-------------------------------
>>> ['\n', ' ', ' ', ' ', ' ', ' ', ' ', '\n', '\t', '\r', '\x0c', '\t']
# \s 匹配非空白
print(re.findall("\S", """我是
你 爸爸\n把,as\tda____9sd\r8\fa9\t0s)(*)(*&*^"""))
-------------------------------
>>>['我', '是', '你', '爸', '爸', '把', .....
\D和\d
# \d 匹配数字,即0-9
print(re.findall("\d", "我是你爸爸把,asda____9sd8a90s)(*)(*&*^"))
-------------------------------
>>> ['9', '8', '9', '0']
# \D 匹配非数字,即不是数字
print(re.findall("\D", "我是你爸爸把,asda____9sd8a90s)(*)(*&*^"))
-------------------------------
>>> ['我', '是', '你', '爸', '爸', '把', ',', 'a', 's',.....
\n和\t
# \n 匹配一个换行符
print(re.findall("\n", """我是
你 爸爸\n把,as\tda____9sd\r8\fa9\t0s)(*)(*&*^"""))
----------------------------------
>>> ['\n', '\n'] #‘是’ 后面有一个换行符
# \n 匹配一个制表符
print(re.findall("\n", """我是
你 爸爸\n把,as\tda____9sd\r8\fa9\t0s)(*)(*&*^"""))
----------------------------------
>>> ['\t', '\t'] #‘你’ 后面有一个Tab 四个空格=一个制表符 \t
^和$
# ^ 匹配字符串的开头
# $ 匹配字符串的结尾
print(re.findall("^egon", "egon asdf 213123 egonafsadfegon"))
print(re.findall("egon$", "egon asdf 213123 egonafsadfegon ")) # 以空格结尾
----------------------------------
>>> ['egon']
>>> []
‘.’ 和[ ]
# ‘ . ’ #匹配任意类型的一个字符
print(re.findall("a.b", "a1b a b aab a,b a_b a\tb a\nb"))
----------------------------------
>>> ['a1b', 'a b', 'aab', 'a,b', 'a_b', 'a\tb'] # 我们发现\n并没有提取到
print(re.findall("a.b", "a1b a b aab a,b a_b a\tb a\nb", re.DOTALL))
----------------------------------
>>> ['a1b', 'a b', 'aab', 'a,b', 'a_b', 'a\tb', 'a\nb'] # DOTALL(DOT:点 ALL:所有 点匹配所有)
# [] 代表匹配其中一个字符,我们可以指定该字符的范围
print(re.findall('d[a-z]', "asddaeraxdsadaraqw412q dhqv chdklqh9v124oiigawr"))
----------------------------------
>>> ['dd', 'ds', 'da', 'dh', 'dk'] # 匹配到以d开头a到z任意一个字母结尾的内容
print(re.findall('b[-1sad f9]', "qk23gba76v8b-b75f74b85bsb85bu23gkqjb gveq278v4g9q4yiu3tb12v6"))
----------------------------------
>>> ['ba', 'b-', 'bs', 'b ', 'b1'] # 单独匹配- 要放在开头或者结尾,放在中间表示范围
print(re.findall('b[^1-9]', "qk23gba76v8b9-b75f74b85bsb85bu23gkqjb gveq278v4g9q4yiu3tb12v6"))
----------------------------------
>>> ['ba', 'bs', 'bu', 'b '] # ^ 在[]内有取反的意思,即不再[]内的字符
‘*’和 +
# * 匹配前一个字符出现0次或者无限次,即可有可无
print(re.findall("ab*","a ab abb abbbbbbbbbbbb bbbbbbbbb"))
----------------------------------
>>> ['a', 'ab', 'abb', 'abbbbbbbbbbbb'] # b出现0次或者更多
# + 匹配前一个字符出现1次或者无限次,即至少有1次
print(re.findall("ab+","a ab abb abbbbbbbbbbbb bbbbbbbbb"))
----------------------------------
>>> ['ab', 'abb', 'abbbbbbbbbbbb'] # b出现1次或者更多
# {n,m}: 左边那个字符出现n次到m次
print(re.findall("ab{2,5}","a ab abb abbbbbbbbbbbb bbbbbbbbb"))
----------------------------------
>>> ['abb', 'abbbbb'] # b出现2次到5次
点星 和 点星问
# .* 贪婪匹配 #.:匹配任意类型字符 # *0次或者无穷多次
print(re.findall("a.*b","123 a1231-==-000b1231231231231b23b"))
----------------------------------
>>> ['a1231-==-000b1231231231231b23b'] # 贪婪匹配会一直匹配到最后一个符合条件的
# .*? 后面加上?,使贪婪变成非贪婪,总是尝试匹配尽可能少的字符
print(re.findall("a.*?b","123 a1231-==-000b1231231231231b23b"))
----------------------------------
>>> ['a1231-==-000b'] # 匹配到第一个就收手
精确匹配是匹配括号里面的东西
# ()分组
print(re.findall('Hello (\d+).*Demo', 'Hello 1234567 World_This is a Rexgex Demo'))
----------------------------------
>>> ['1234567'] # 只提取到分组内东西
# 取消分组
print(re.findall('Hello (?:\d+).*Demo', 'Hello 1234567 World_This is a Rexgex Demo'))
----------------------------------
>>> ['Hello 1234567 World_This is a Rexgex Demo']
# | 或者
print(re.findall("compan(?:ies|y)","Too many companies have gone bankrupt, and the next one is my company'"))
----------------------------------
>>> ['companies', 'company'] # 以ies结尾或者yjiewei
\ 转义符
print(re.findall('a\\\\c','a\c a1c aac')) #对于正则来说a\\c确实可以匹配到a\c,但是在python解释器读取a\\c时,会发生转义,然后交给re去执行,所以抛出异常
print(re.findall(r'a\\c','a\c a1c aac')) #对于正则来说a\\c确实可以匹配到a\c,但是在python解释器读取a\\c时,会发生转义,然后交给re去执行,所以抛出异常
----------------------------------
>>> ['a\\c']
['a\\c']
知识点:
?!pattern,表示在没有配到pattern的字符串的前提下,再进行后续的正则表达式匹配,后续匹配仍然从被匹配字符串的头开始
?=pattern,表示在配到pattern的字符串的前提下,再进行后续的正则表达式匹配,后续匹配仍然从被匹配字符串的头开始
解析:
我们可以用循环来解释一下这两个内容
# ?!pattern
data = 1244xc
print(re.search("(?!^[0-9]+$)(?!^[a-zA-Z]+$)^[0-9A-Za-z]{6}$", data).group())
if re.search('^[0-9]+$', data) is None:
if re.search('^[a-zA-Z]+$', data) is None:
if re.search('^[0-9A-Za-z]{6}$', data) is not None:
print(re.search('^[0-9A-Za-z]{6}$', data).group())
else:
print("密码全部是数字!")
else:
print("密码全部是字母!")
else:
print("密码不是6位")
--------------------------------------
>>> 1244xc
>>> 1244xc
# ?=pattern
data2 = '12124sfS@#'
print(re.search("(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[!@#%&])^([a-zA-Z0-9!@#%&]){6,}$",data2).group())
if re.search('.*[A-Z]', data2):
if re.search('.*[a-z]', data2):
if re.search('.*[0-9]', data2):
if re.search('.*[!@#%&]', data2):
print(re.search('^([a-zA-Z0-9!@#%&]){6,}$', data2).group())
else:
print("密码不含大写字母!")
else:
print("密码不含小写字母!")
else:
print("密码不含数字")
else:
print("密码不含特殊字符")
--------------------------------------
>>> 12124sfS@#
>>> 12124sfS@#