1_正则表达式(python)
文章目錄
- 介紹
- 例子
- 其他簡(jiǎn)單例子
- 常用操作符(`.`,`*`,`{}`,`?`,`+`,`^`...)
- 常用匹配字符串
- 匹配某個(gè)字符串
- `.` 點(diǎn) , 匹配符任意的字符
- 任意的數(shù)字 `\d`
- `\s` 匹配空白的字符
- 任意的非數(shù)字 `\D`
- `\w` 匹配的是 a-z 和A-z 以及數(shù)字0-9和下劃線
- `\W` 匹配 大小寫(xiě)字母 數(shù)字 和 下劃線 以外的字符
- `*`匹配多個(gè)字符
- `?` 問(wèn)號(hào) 匹配一個(gè)或者0個(gè)字符
- `{m}`匹配m個(gè)字符
- `{m,n}` 匹配 m到n個(gè)字符
- `{m,} {,n}` 實(shí)現(xiàn) 長(zhǎng)度的大于等于, 小于等于
- 脫字號(hào) `^` 以 ...開(kāi)始,
- `'$' ` 以...結(jié)尾
- `'|' ` 匹配多個(gè)字符串或者表達(dá)式
- `[ ]` 組合的方式
- `| ` 和`[ ]` 兩者之間的差異
- `+` 號(hào) 的使用
- 轉(zhuǎn)義字符的使用
- 常用方法
- `re.search`
- `re.match`
- `re.findall`
- `re.split`
- `re.finditer`
- `re.sub`
- `subn`
- `re.compile`
- re.escape(pattern) 處理轉(zhuǎn)義字符
- 常用方法(函數(shù))`sub` 案例
- `re`匹配到的對(duì)象
- 返回對(duì)象的常用屬性
- 返回對(duì)象的常用方法
- 貪婪模式和非貪婪模式
- 如何非貪婪模式?
- 關(guān)于分組
- `()`分組 `\num` 別名
- `(...)\number`
- 常用的 `flags`
- re.A
- re.DEBUG
- re.I
- re.M
- re.S
- re.X
- 指定多個(gè) `flags` 的方式
- 一些不常見(jiàn)的匹配符號(hào)
- `(?P=name)`
- `(?#...)`
- 正則 斷言匹配
- `(?=...)` => 匹配 某字符跟隨某某字符 ,匹配前者。
- `(?!...)`=> 匹配 某字符串 后面沒(méi)跟著某某字符。匹配前者。
- `(?<=...)` => 匹配前面是某某字符的某字符。匹配后者
- `(?<!...)`=> 匹配 前面不是某某字符我就匹配某字符。 匹配后者
- `(?(id/name)yes-pattern|no-pattern)`
- 常用正則速查
介紹
python re 模塊-正則- python 官方文檔 中文
正則語(yǔ)法 python
書(shū)籍推薦
Jeffrey E. F. Friedl的《Mastering Regular Expressions》一書(shū),
Michael Fitzgerald的《Introducing Regular Expressions》,
Jan Goyvaerts和Steven Levithan寫(xiě)的《Regular Expressions Cookbook》
都是O'Reilly出版社出版,這些書(shū)都非常受歡迎。
regex101 網(wǎng)站
regex101對(duì)于新手是特別有用的網(wǎng)站,可以自動(dòng)生成正則表達(dá)式的解讀。
正則表達(dá)式測(cè)試網(wǎng)站
正則可視化測(cè)試網(wǎng)站
正則表達(dá)式用于搜索、 替換和解析 字符串。 正則表達(dá)式遵循一定的語(yǔ)法規(guī)則, 使用非常靈活, 功能強(qiáng)大。 使用正則表達(dá)式編寫(xiě)一些邏輯驗(yàn)證非常方便, 例如電子郵件地址格式的驗(yàn)證。
正則表達(dá)式是對(duì)字符串(包括普通字符(例如, a 到 z 之間的字母) 和特殊字符) 操作
的一種邏輯公式, 就是用事先定義好的一些特定字符、 及這些特定字符的組合, 組成一個(gè)“規(guī) 則字符串” , 這個(gè)“規(guī)則字符串” 用來(lái)表達(dá)對(duì)字符串的一種過(guò)濾邏輯, 正則表達(dá)式是一種文 本模式, 模式描述在搜索文本時(shí)要匹配一個(gè)或多個(gè)字符串。
一開(kāi)始的例子 如果看不懂 可以先 跳過(guò)。
然后看 search 和 match 方法 。 接著 回過(guò)頭來(lái) 看 常用匹配字符串
然后順序往下看。
當(dāng)然也可以根據(jù)自己的想法 ,隨意觀看。
例子
In [16]: import reIn [17]: pat=r'P(Y|YT|YTH|YTHO)?N'In [18]: p=re.compile(pat) # 面向?qū)ο? 編譯 。 多次使用的正則In [19]: p.findall("i love PN PYN PYTN PYTHN PYTHON PDADN") Out[19]: ['', 'Y', 'YT', 'YTH', 'YTHO']In [21]: p.search("i love PN PYN PYTN PYTHN PYTHON PDADN") Out[21]: <_sre.SRE_Match object; span=(7, 9), match='PN'># 當(dāng)然你也可以使用這種方式 單次 使用。 In [22]: re.findall(pat,"i love PN PYN PYTN PYTHN PYTHON PDADN") Out[22]: ['', 'Y', 'YT', 'YTH', 'YTHO'] # ---------------------------In [23]: pat=r'PYTHON+'In [24]: p=re.compile(pat) In [25]: p.findall("PYTHONN PYTHONNNN PYTHONN PYTHON PYTHO") Out[25]: ['PYTHONN', 'PYTHONNNN', 'PYTHONN', 'PYTHON']# -------------------------------In [27]: pat=r'PY[TH]ON'In [28]: p=re.compile(pat)In [29]: p.findall("PYTON PYHON PYTHON") Out[29]: ['PYTON', 'PYHON']# ------------------------------ # [^5] 將匹配除 '5' 以外的字符 # 那這里就是 匹配除了 TH以外的字符 中括號(hào)這個(gè)位置 # ? 表示0 次或者 1次 In [30]: pat=r'PY[^TH]?ON'In [31]: p=re.compile(pat)In [34]: p.findall("PYON PYaON PYTHON PYcON PYTON PYAON") Out[34]: ['PYON', 'PYaON', 'PYcON', 'PYAON']# ------------------- In [35]: pat='PY{0,3}N' # 圖片中的寫(xiě)法 {:3} 這種寫(xiě)法 不生效 無(wú)法匹配In [36]: p=re.compile(pat)In [37]: p.findall("PYNPYNPYNPYN PYYN PYYYN PYYYYYN") Out[38]: ['PYN', 'PYN', 'PYN', 'PYN', 'PYYN', 'PYYYN']
In [37]: pat=r'^[A-Za-z]+$' # 既然 + 是 1 次或者無(wú)限次 # 那么 我們也可以改為 ? 0次 或者 1次 那就只匹配 1個(gè) 字母了 # 字母 In [38]: p=re.compile(pat)In [39]: p.match("adsfadfasd") Out[39]: <_sre.SRE_Match object; span=(0, 10), match='adsfadfasd'>In [40]: p.match("adsfadfasdADSFAKSD...")In [41]: p.match("adsfadfasdADSFAKSD") Out[41]: <_sre.SRE_Match object; span=(0, 18), match='adsfadfasdADSFAKSD'># ------------------------------ # 字母和數(shù)字 In [43]: pat=r'^[A-Za-z0-9]+$'In [44]: p=re.compile(pat) In [46]: p.search("dasfasdfsdf23141") Out[46]: <_sre.SRE_Match object; span=(0, 16), match='dasfasdfsdf23141'># -------------------------------- # 整數(shù) In [49]: pat=r'^-?\d+$'In [50]: p=re.compile(pat)In [51]: p.search("123") Out[51]: <_sre.SRE_Match object; span=(0, 3), match='123'>In [52]: p.search("+123")In [53]: p.search("-123") Out[53]: <_sre.SRE_Match object; span=(0, 4), match='-123'>In [54]: p.search("-123.2")# ------------------ # 正整數(shù) In [56]: pat=r'^[0-9]*[1-9][0-9]*'In [57]: p=re.compile(pat)In [58]: p.search("31434") Out[58]: <_sre.SRE_Match object; span=(0, 5), match='31434'>In [59]: p.search("031434") Out[59]: <_sre.SRE_Match object; span=(0, 6), match='031434'>In [60]: p.search("0031434") Out[60]: <_sre.SRE_Match object; span=(0, 7), match='0031434'>In [61]: p.search("-31434")# -------------------------- # 郵編 In [62]: pat=r'[1-9]\d{5}'In [63]: p=re.compile(pat)In [64]: p.search("314200") Out[64]: <_sre.SRE_Match object; span=(0, 6), match='314200'>In [65]: p.search("31420000") Out[65]: <_sre.SRE_Match object; span=(0, 6), match='314200'>In [66]: p.search("00031420000") Out[66]: <_sre.SRE_Match object; span=(3, 9), match='314200'># ------------------------ In [68]: pat=r'[\u4e00-\u9fa5]' # 中文字符In [69]: p=re.compile(pat)In [70]: p.search("把酒問(wèn)青天") Out[70]: <_sre.SRE_Match object; span=(0, 1), match='把'>In [71]: p.findall("把酒問(wèn)青天") Out[71]: ['把', '酒', '問(wèn)', '青', '天'] # ------------------------------------ # 國(guó)內(nèi)電話號(hào)碼 In [75]: pat=r'\d{3}-\d{8}|\d{4}-\d{7}'In [76]: p=re.compile(pat)In [77]: p.search("021-6891336")In [78]: p.search("021-68913536") Out[78]: <_sre.SRE_Match object; span=(0, 12), match='021-68913536'># ------------------------------------- # 匹配手機(jī)號(hào)碼 import re # pattern='\d\d\d\d\d\d\d\d\d\d\d' pattern='1[35789]\d\d\d\d\d\d\d\d\d' pattern='1[35789]\d{9}' # 和上面的式子 是不是等價(jià)呢? 是的。 s='13456788765' o=re.match(pattern,s) print(o)#電話號(hào)碼 區(qū)號(hào)-座機(jī)號(hào) 010-3762266 0342-8776262In [12]: import reIn [13]: pattern='1[35789]\d{9}'In [14]: s='13456788765'...: o=re.match(pattern,s)In [15]: o Out[15]: <_sre.SRE_Match object; span=(0, 11), match='13456788765'>
In [2]: import reIn [3]: pat='\d+.\d+.\d+.\d+'In [4]: p=re.compile(pat) # 很明顯 # ip 地址 沒(méi)有 大于 255 的 # 且長(zhǎng)度 是 1 到 3 In [5]: p.findall("255.255.255.255 3333.333.333.333") Out[5]: ['255.255.255.255 ', '3333.333.333.333']In [14]: pat='\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}'In [15]: p=re.compile(pat) # 這個(gè)很明顯 也是有點(diǎn)問(wèn)題的 In [16]: p.findall("255.255.255.255 3333.333.333.333") Out[16]: ['255.255.255.255', '3333.333.333']
其他簡(jiǎn)單例子
# 1. 驗(yàn)證手機(jī)號(hào)碼 text = "12567347199" ret = re.match('1[34578]\d{9}', text) print(ret.group())# 2. 驗(yàn)證郵箱 text = "pis1@qq.com" ret = re.match('\w+@[a-z0-9]+\.[a-z]+', text) print(ret.group())# 3. 驗(yàn)證 url 協(xié)議 text = "https://www.baidu.com/" ret = re.match('(http|https|ftp)://[^\s]+', text) # 豎線 就是 或的 意思 print(ret.group())# 4. 驗(yàn)證身份證 text = "51152319930228159x" ret = re.match('\d{17}[\dxX]', text) print(ret.group())import re print('------案例1------') #匹配出一個(gè)字符串首字母為大寫(xiě)字符,后邊都是小寫(xiě)字符,這些小寫(xiě)字母可有可無(wú) pattern='[A-Z][a-z]*' s='Hello' s='HEllo' o=re.match(pattern,s) print(o)print('------案例2------') #匹配出有效的變量名 (字母 、數(shù)字 下劃線 ,而且數(shù)字不能開(kāi)頭) # pattern='[a-zA-Z_][a-zA-Z0-9_]*' pattern='[a-zA-Z_]\w*' s='userName' s='age' s='a' s='_qwe' # s='3er' o=re.match(pattern,s) print(o) print('-------案例3----------') #匹配出1-99直接的數(shù)字 pattern='[1-9]\d?' s='2' s='99' s='100' s='0' o=re.match(pattern,s) print(o) print('----------案例4--------------') #匹配出一個(gè)隨機(jī)密碼8-20位以內(nèi) (大寫(xiě)字母 小寫(xiě)字母 下劃線 數(shù)字) pattern='\w{8,20}' s='123456789' s='abc123qwe_' s='1234567#' o=re.match(pattern,s) print(o)
常用操作符(.,*,{},?,+,^…)
常用匹配字符串
# 重復(fù)數(shù)量符號(hào) ''' * :0次或多次 ? :0次或1次 + :至少1次 {m} :重復(fù)m次 {m,n} :重復(fù)m到n次 {m} :至少重復(fù)m次 {m,} :長(zhǎng)度的大于等于, {,n} :小于等于 '''# 常用的 匹配字符串 ''' . 匹配任意一個(gè)字符(除了\n) [] 匹配列表中的字符 \w 匹配字母、數(shù)字、下劃線,即a-z,A-Z,0-9,_ \W 匹配不是字母、數(shù)字、下劃線 \s 匹配空白字符,即空格(\n,\t) \S 匹配不是空白的字符 \d 匹配數(shù)字,即0-9 \D 匹配非數(shù)字的字符 '''這里也有一些特殊字符的展示
比如 十六進(jìn)制 Unicode碼 \u0000:\uFFFF
ASCII碼 \x00:\xFF,
-
中文字符的 Unicode 范圍 \u4e00-\u9fa5
-
ascii 只能匹配 英文的。 范圍為 0- 255 一共 256 個(gè)字符
關(guān)于控制字符 \cA-\cZ 對(duì)應(yīng)的是 ascii 中 1-26 的控制字符 。但是 python不支持 \cA 這種寫(xiě)法
所以不建議 使用 建議使用 十六進(jìn)制碼 或者 \t 這種寫(xiě)法(前提是那個(gè)字符有類似的寫(xiě)法)
演示
看完這個(gè)應(yīng)該就能理解我想說(shuō)的是什么了。
import re str_=""" 中國(guó)牛逼 2020-12-12 2020年12月4日19:47:07 """ pat=r'[\n]' pat1=r'[\x0A]' re.findall(pat,str_) re.findall(pat1,str_)匹配某個(gè)字符串
# match, 匹配某個(gè)字符串 text = 'hello' ret = re.match('he', text) # match 只會(huì)匹配前面的字符 ahello 就匹配不到了 print(ret.group()) # group 把提匹配到的字符串提取出來(lái). 點(diǎn) , 匹配符任意的字符
# 點(diǎn),匹配符任意的字符 text = 'hello' ret = re.match('.', text) # 但是只能匹配一個(gè)字符,但是 不能匹配換行符\n print(ret.group())任意字符不包括換行符
真正的任意字符可以寫(xiě)成 多種方式 [\w\W] [\s\S] [\d\D] 或者 使用 flags 標(biāo)志 re.S
任意的數(shù)字 \d
# 任意的數(shù)字 \d (0-9) text = "1" ret = re.match('\d', text) print(ret.group())\s 匹配空白的字符
# \s 匹配空白的字符(例如:\n \r \t ,空格) text = " a b" ret = re.match('\s', text) print(ret.group())任意的非數(shù)字 \D
# 任意的非數(shù)字 \D text = "+a" ret = re.match('\D', text) print(ret.group())\w 匹配的是 a-z 和A-z 以及數(shù)字0-9和下劃線
# \w 匹配的是 a-z 和A-z 以及數(shù)字0-9和下劃線text = "ab" ret = re.match('\w', text) print(ret.group())\W 匹配 大小寫(xiě)字母 數(shù)字 和 下劃線 以外的字符
# \W 與 \w 相反 匹配的text = "+ab"ret = re.match('\W', text)print(ret.group())*匹配多個(gè)字符
# 匹配多個(gè)字符# * 星號(hào)可以匹配 0個(gè) 或者任意多個(gè) 字符 text = "abdc" ret = re.match('\d*', text) # 這個(gè) '\d*' 匹配任意多個(gè)數(shù)字 print(ret.group())# + 加號(hào) 匹配一個(gè)或者多個(gè)字符 text = "+abdc" # 這個(gè) '\w+'' 匹配一個(gè)以上 a-z 和A-z 以及數(shù)字0-9和下劃線 組成的 字符串 ret = re.match('\w+', text) # 因?yàn)?是從開(kāi)頭開(kāi)始匹配 ,所以這里會(huì)報(bào)錯(cuò) 因?yàn)殚_(kāi)頭 匹配不到 print(ret.group()) import re print('--------*的使用------------') pattern='\d*' s='123qwe' s='123456qwe' s='qwe' o=re.match(pattern,s) print(o)? 問(wèn)號(hào) 匹配一個(gè)或者0個(gè)字符
# ? 問(wèn)號(hào) 匹配一個(gè)或者0個(gè)字符 text = "abdc+"ret = re.match('\w?', text) print(ret.group()) print('--------?的使用------------') pattern='\d?' s='123qwe' s='1qwe' s='123456qwe' s='qwe' o=re.match(pattern,s) print(o){m}匹配m個(gè)字符
# {m}匹配m個(gè)字符 text = "abdc+" ret = re.match('\w{2}', text) # 匹配兩個(gè)字符 print(ret.group()) print('---------{m}-----------') pattern='\d{2}' pattern='\d{3}' pattern='\d{4}' s='123qwe' o=re.match(pattern,s) print(o){m,n} 匹配 m到n個(gè)字符
# {m,n}匹配m到n個(gè)字符 text = "abdcdanmd;a" ret = re.match('\w{1,5}', text) print(ret.group()) print('---------{m,n}-----------') pattern='\d{2,5}' s='123qwe' s='123456qwe' s='qwe' o=re.match(pattern,s) print(o){m,} {,n} 實(shí)現(xiàn) 長(zhǎng)度的大于等于, 小于等于
print('---------{m,}-----------') pattern='\d{2,}' s='123qwe' s='123456qwe' s='qwe' o=re.match(pattern,s) print(o) # 表示 空字符串。長(zhǎng)度為 0 的字符串。 s = '' o1 = re.match(r'^$', s) print(o1) # 有匹配結(jié)果,匹配到空字符串 s = '1' print(o1) # 無(wú)匹配結(jié)果,返回 None- 指定開(kāi)放區(qū)間,省略第2個(gè)值,保留逗號(hào)。例如 a{4, } 匹配4個(gè)或更多個(gè)連續(xù)的字符a。
脫字號(hào) ^ 以 …開(kāi)始,
# 脫字號(hào) '^' 以 ...開(kāi)始, # 放在中括號(hào)[]里面 是取反的意思 text = "hello.py" ret = re.search('^h\w*\.py$', text) # match 是從開(kāi)始去匹配 和 脫字號(hào) 是一樣的功能 print(ret.group())'$' 以…結(jié)尾
# '$' 以...結(jié)尾 text = "pis1@163.com" ret = re.match('\w+@163.com$', text) # match 是從開(kāi)始去匹配 和 脫字號(hào) 是一樣的功能 print(ret.group())'|' 匹配多個(gè)字符串或者表達(dá)式
# `'|' ` 匹配多個(gè)字符串或者表達(dá)式 或者的 意思 要么 的意思 text = "http" ret = re.match('(http|https|ftp)$', text) # match 是從開(kāi)始去匹配 和 脫字號(hào) 是一樣的功能 print(ret.group()) # 匹配多個(gè)字符串 import re pattern='aa|bb|cc' s='aa' o=re.match(pattern,s) print(o)s='bb' o=re.match(pattern,s) print(o)s='my name is cc' o=re.search(pattern,s) o=re.match(pattern,s) print(o) print('匹配0-100之間所有的數(shù)字') #匹配0-100之間所有的數(shù)字 0-99|100 pattern=r'[1-9]?\d$|100$' s='1' s='11' s='99' s='100' s='1000' o=re.match(pattern,s) print(o)關(guān)于 ! 和 ^ 以及 $ 搭配使用
(^|\\s) 就代表 可以是 以 '' 就是沒(méi)有字符開(kāi)始 或者 \s 空白字符開(kāi)始 的 字符
同理 $ 這就是 以沒(méi)有"" 結(jié)尾 或者 空字符結(jié)尾
[ ] 組合的方式
# [ ] 組合的方式 ,只要,滿足中括號(hào) 中的字符,就可以匹配 text = "a" ret = re.match('[a1]', text) # 匹配 a和 1 print(ret.group()) 8.1 text = "0731-88888888"# 特殊字符 需要 -前面轉(zhuǎn)義 加一個(gè)\ \d是數(shù)字匹配 寫(xiě)一個(gè) + 加號(hào) 就是匹配到 多個(gè)字符 ret = re.match('[\d\-]+', text) print(ret.group())# 8.2 中括號(hào) 代替 \d 以及 反斜杠 \w text = "1213" ret = re.match('[^0-9]+', text) # 這個(gè) ^0-9 是 匹配非0-9的字符 前面加了一個(gè)脫字號(hào) print(ret.group())# 8.2 中括號(hào) 代替 以及 反斜杠 \w text = "1213" ret = re.match('[a-zA-Z0-9_]', text) # 這個(gè) ^0-9 是 匹配非0-9的字符 print(ret.group()) # 8.2 中括號(hào) 代替 以及 反斜杠 \W text = "*" ret = re.match('[^a-zA-Z0-9_]', text) # 這個(gè) ^0-9 是 匹配非0-9的字符 print(ret.group())| 和[ ] 兩者之間的差異
# 擇一匹配符 和 列表使用差異 import re # pattern=r'[xyz]' # s='y' # o=re.match(pattern,s) # print('使用列表[]:',o) # # pattern=r'x|y|z' # s='y' # o=re.match(pattern,s) # print('擇一匹配符|:',o) # print('字符集([])和擇一匹配符(|)的用法,及它們的差異') # pattern=r'[ab][cd]' # s='ac' # s='ab' # o=re.match(pattern,s) # print(o) # pattern=r'ab[cd]' # # s='ab' # # s='abc' # s='abd' # o=re.match(pattern,s) # print(o) pattern='ab|cd' # s='abc' # s='abd' # s='cd' s='ad' s='ac' o=re.match(pattern,s) print(o)+ 號(hào) 的使用
print('--------+的使用------------') pattern='\d+' # s='123qwe' # s='1qwe' # s='123456qwe' s='qwe' o=re.match(pattern,s) print(o)轉(zhuǎn)義字符的使用
當(dāng)然 我們也可以使用 raw 原生字符 s=r'\t123' 類似這樣的語(yǔ)法 會(huì)經(jīng)常 看到。
# 轉(zhuǎn)義字符的使用 print('d:\\a\\b\\c') print('\nabc') print('\\nabc') print('\t123') print('\\t123')import re s='\\t123' # pattern='\\\\t\d*' pattern=r'\\t\d*' o=re.match(pattern,s) print(o)s='\\\\t123' # pattern='\\\\\\\\t\d*' pattern=r'\\\\t\d*' o=re.match(pattern,s) print(o) # 轉(zhuǎn)義字符 和 原生字符串 text = "apple price is $299" ret = re.search("\$\d+", text) # 提取價(jià)格 \ 轉(zhuǎn)義 \$ 只想 讓他作為 普通字符串 print(ret.group())# 原生字符串 text = "\\n" # python 中的 轉(zhuǎn)義字符 把 換行符 轉(zhuǎn)換成一個(gè) 普通反斜杠 text = r"\n" # 前面加一個(gè)r 就是原生的意思 r 就是 raw 原生的意思 別的 正則里面也可以使用 print(text)# 反斜杠 正則和 python 的 \ 反斜杠 都是 轉(zhuǎn)義 ,所以 想要打印出反斜杠 需要4 個(gè)反斜杠text = '\c' # 這里在python 語(yǔ)言中 '\\n'='\n' # python中\(zhòng)\\\c => \\c # 正則中 \\c= > \c # ret = re.match('\\\\c', text) # 轉(zhuǎn)義 ret = re.match(r'\\c', text) # 原生字符串的方式 print(ret.group())常用方法
常用查詢,主要功能函數(shù)
re.search
re.match
# match 方法的使用 import re s='hello python' pattern='hello' o=re.match(pattern,s) # ----------------- print(o) print(dir(o)) print(o.group()) #返回匹配的字符串 print(o.span()) print(o.start()) # --------------------- print('flags參數(shù)的使用') s='hello python' pattern='Hello' o=re.match(pattern,s,flags=re.I) # re.I # re.IGNORECASE 這兩個(gè)是一樣的。 # 都是忽略大小寫(xiě)print(o) print(o.group())# ------------------- In [3]: print(o) <_sre.SRE_Match object; span=(0, 5), match='hello'>In [4]: print(dir(o)) ['__class__', '__copy__', '__deepcopy__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'end', 'endpos', 'expand', 'group', 'groupdict', 'groups', 'lastgroup', 'lastindex', 'pos', 're', 'regs', 'span', 'start', 'string'] # 這里是這個(gè) match 對(duì)象的屬性In [5]: print(o.group()) #返回匹配的字符串 helloIn [6]: print(o.span()) # 匹配到的字符串的 索引范圍 (0, 5)In [7]: print(o.start()) # 匹配到的字符的 開(kāi)始位置 0In [8]: print('flags參數(shù)的使用') flags參數(shù)的使用In [9]: s='hello python'...: pattern='Hello'...: o=re.match(pattern,s,flags=re.I)# re.I # re.IGNORECASE 這兩個(gè)是一樣的。 # 都是忽略大小寫(xiě) In [10]:In [10]: print(o) <_sre.SRE_Match object; span=(0, 5), match='hello'>In [11]: print(o.group()) hellore.findall
import re print('---------findall-------------') s='first 1 second 2 third 3' pattern=r'\w+' result=re.findall(pattern,s) print(result)re.split
import re print('----------split-------------') s='first 11 second 22 third 33' pattern=r'\d+' result=re.split(pattern,s) print(result) result=re.split(pattern,s,maxsplit=2) print(result) # split 分割函數(shù) text = "hello&world ni hao" ret = re.split('[^a-zA-Z]', text) # 以非英文字母為分割 符號(hào) print(ret)re.finditer
import re print('---------finditer-------------') s='first 1 second 2 third 3' pattern=r'\w+' result=re.finditer(pattern,s) print(result) for i in result:print(i.group(),end='\t') print()re.sub
import re print('--------sub-------------') phone='2004-959-559 # 這是一個(gè)國(guó)外電話號(hào)碼' #將phone中的注釋去掉 pattern=r'#.*$' result=re.sub(pattern,'',phone) print('sub:',result) pattern=r'#\D*' result=re.sub(pattern,'',phone) print('sub:',result)subn
執(zhí)行與相同的操作sub(),但返回一個(gè)元組 (new_string, number_of_subs_made) .
import re phone='2004-959-559 # 這是一個(gè)國(guó)外電話號(hào)碼' #將phone中的注釋去掉 pattern=r'#.*$' print('---------subn-----------') result=re.subn(pattern,'',phone) print(result) print(result[0]) print(result[1])re.compile
re.escape(pattern) 處理轉(zhuǎn)義字符
re.escape(pattern)
在中轉(zhuǎn)義特殊字符 模式 . 如果要匹配可能包含正則表達(dá)式元字符的任意文本字符串,則此選項(xiàng)非常有用。例如:
常用方法(函數(shù))sub 案例
import re # 實(shí)際的案例 替換 函數(shù) html = ''' <dd class="job_bt"><h3 class="description">職位描述:</h3><div class="job-detail"><p>崗位職責(zé):</p> <p>1、完成對(duì)復(fù)雜網(wǎng)站的數(shù)據(jù)抓取和交互模擬;</p> <p>2、通過(guò)各種渠道或方式對(duì)相關(guān)網(wǎng)站進(jìn)行抓取;</p> <p>3、不斷完善并維護(hù)相關(guān)網(wǎng)站的抓取,使之穩(wěn)定運(yùn)行,核心邏輯必須有單元測(cè)試;</p> <p>4、善于靈活運(yùn)用各種非爬蟲(chóng)技術(shù)解決爬蟲(chóng)相關(guān)問(wèn)題;</p> <p>5、隨時(shí)響應(yīng)并解決突發(fā)問(wèn)題;</p> <p>6、完成領(lǐng)導(dǎo)交辦的其他工作。</p> <p><br></p> <p>任職要求:</p> <p>1、本科以上學(xué)歷,三年以上網(wǎng)站抓取經(jīng)驗(yàn),有電商網(wǎng)站、秒殺相關(guān)抓取經(jīng)驗(yàn);</p> <p>2、有較強(qiáng)的網(wǎng)站分析能力,熟知各種反爬措施及相關(guān)解決辦法</p> <p>技能要求;</p> <p>3、熟練使用eventlet、gevent、requests、selenium等技術(shù)實(shí)現(xiàn)高并發(fā)穩(wěn)定抓取;</p> <p>4、熟練使用消息隊(duì)列(MQ)、celery等異步框架實(shí)現(xiàn)分布式任務(wù)處理;</p> <p>5、熟知HTTP、TCP、Socket等底層知識(shí);</p> <p>6、熟練掌握Fiddler、Http debugger等抓捕工具;</p> <p>7、熟悉MySQL、MongoDB基本使用;</p> <p>8、熟悉Scapy,熟悉Javascript,有一定的分析能力;</p> <p>9、能使用mock進(jìn)行單元測(cè)試;</p> <p>10、善于溝通、有團(tuán)隊(duì)協(xié)作精神。</p> <p><br></p> <p>我們的團(tuán)隊(duì)成員都是80后、90后,我們是充滿激情和干勁的團(tuán)隊(duì),我們是有夢(mèng)想有追求的團(tuán)隊(duì)……</p> <p>如果你有滿腔熱忱,如果你不想碌碌無(wú)為,如果你想通過(guò)自己的努力成為合伙人……</p> <p>來(lái)吧!朋友,加入我們,我們會(huì)給你釋放夢(mèng)想的平臺(tái),我們會(huì)讓你的美夢(mèng)成真……</p> <p>期待有為的你加入!!!</p> <p> </p> <p>為了讓我們的小伙伴能夠快樂(lè)、健康的在一起為了夢(mèng)想而努力,我們提供了以下多種福利及文化活動(dòng):</p> <p>1、每天工作8小時(shí),彈性工作時(shí)間;</p> <p>2、公司年度健康體檢,小伙伴在為公司默默奉獻(xiàn)的同時(shí),公司也時(shí)刻關(guān)注著他們的健康。</p> <p>3、量身定制的培訓(xùn)計(jì)劃,讓員工在我們細(xì)致入微的幫助下更快的融入團(tuán)隊(duì)。</p> <p>4、豐富的企業(yè)文化活動(dòng):</p> <p>? 每天:美味的零食和飲品;</p> <p>? 每?jī)芍?#xff1a;組織大家去打乒乓球、羽毛球,小伙伴的健康是我們一直關(guān)注的;</p> <p>? 每月:家人生日會(huì)(給每位壽星唱著生日快樂(lè)歌,分享美味可口的蛋糕,盡享溫馨時(shí)刻);</p> <p>? 季度:團(tuán)隊(duì)建設(shè)、拓展活動(dòng);</p> <p>? 年度:大型年會(huì)(辛苦了一年的匯游科技家人,一起收獲一起分享)。</p> <p>5、每年1次調(diào)薪,兩次豐厚的績(jī)效獎(jiǎng)金,付出與回報(bào)永遠(yuǎn)成正比哦。</p> <p>6、節(jié)日禮品、生日禮品、結(jié)婚生子禮金等。</p> <p>7、每天午餐補(bǔ)助,每月全勤獎(jiǎng)勵(lì)。</p> <p>…………</p> <p> </p> <p> </p> <p>匯游科技祝您面試成功!</p></div></dd> '''ret = re.sub('<.+?>', '', html) # 非貪婪 模式 ,把 非標(biāo)簽的數(shù)據(jù)替換掉了 print(ret)re匹配到的對(duì)象
比如match 或者search 匹配到 的對(duì)象 也就是 這些函數(shù)的 返回值
可以這樣理解。
<_sre.SRE_Match object; span=(0, 11), match='33.33.33.33'> 這個(gè)就是一個(gè)返回對(duì)象 。
match對(duì)象
匹配對(duì)象
返回對(duì)象的常用屬性
返回對(duì)象的常用方法
貪婪模式和非貪婪模式
re 默認(rèn)是貪婪模式
如何非貪婪模式?
*?, +?, ?? 這些符號(hào) 就代表非貪婪 模式 (也叫最小匹配操作符)
比如 你使用 (.*?) 匹配任意字符 但是 是非貪婪 模式 。 只匹配最少的數(shù)據(jù)。
關(guān)于分組
(...)
匹配圓括號(hào)內(nèi)的任何正則表達(dá)式,并指示組的開(kāi)始和結(jié)束;組的內(nèi)容可以在執(zhí)行匹配后檢索,稍后在字符串中與 \number 特殊順序,如下所述。匹配文字 '(' 或 ')' 使用 \( 或 \) 或?qū)⑺鼈兝ㄔ谧址愔?#xff1a; [(] , [)] .
\number
匹配同一號(hào)碼組的內(nèi)容。組從1開(kāi)始編號(hào)。例如, (.+) \1 'the the' 或 '55 55' ,但不匹配 'thethe' (注意組后的空格)。
()分組 \num 別名
import re# 示例 1 匹配座機(jī)號(hào)碼 使用 ( ) 括號(hào) 分組 print('匹配座機(jī)號(hào)碼') # 匹配座機(jī)號(hào)碼 區(qū)號(hào){3,4}-電話號(hào)碼{5,8} 010-43222 0432-447727 pattern=r'\d{3,4}-[1-9]\d{4,7}$' pattern=r'(\d{3,4})-([1-9]\d{4,7}$)' s='010-786545' o=re.match(pattern,s) print(o) print(o.group()) print(o.group(1)) print(o.group(2)) # print(o.groups()) # print(o.groups()[0]) # 這樣子 group() 返回的是字符串 所以這種方式 就是類似元組 切片 索引訪問(wèn) 字符串。 # print(o.groups()[1])print('匹配出網(wǎng)頁(yè)標(biāo)簽內(nèi)的數(shù)據(jù)') # 示例 2 分組示例 \num # pattern=r'<.+><.+>.+</.+></.+>'pattern=r'<(.+)><(.+)>.+</\2></\1>' s='<html><head>head部分</head></html>' # s='<html><title>head部分</head></body>' o=re.match(pattern,s) print(o)
# ( ) \1 # 正確示范,()有分組作用,正則表達(dá)式中\(zhòng)1可以取到分組的第一個(gè) import rehtml_str = "<h1>hahaha</h1>" ret = re.match(r"<(\w*)>.*</\1>", html_str) print(ret.group())
# ( ) \1 # 正確示范,()有分組作用,正則表達(dá)式中 \1 和 \2取值順序 import rehtml_str = "<body><h1>hahaha</h1></body>" ret = re.match(r"<(\w*)><(\w*)>.*</\2></\1>", html_str) print(ret.group())
# 示例 3 分組起別名 # (?p<name>) 分別起組名 # (?p=name) 引用別名為name分組匹配到的字符串# 示例html標(biāo)簽 .+ 匹配 起別名 # <(?P<k_html>.+)>#<body><h1><div><div></div></div></h1></body> print('(?P<name>) 分別起組名') pattern=r'<(?P<k_html>.+)><(?P<k_head>.+)>.+</(?P=k_head)></(?P=k_html)>' s='<html><head>head部分</head></html>' # s='<html><title>head部分</head></body>' o=re.match(pattern,s) print(o)
通過(guò)觀察可以發(fā)現(xiàn) 取了別名 就有了 groupdict 了
# -------------------------------(?P<name>) #命名的格式 (注意P是大寫(xiě)的) (?P=name) #取值的格式 # import rehtml_str = "<body><h1>hahaha</h1></body>" ret = re.match(r"<(?P<p1>\w*)><(?P<p2>\w*)>.*</(?P=p2)></(?P=p1)>", html_str) print(ret.group())
import re# 分組 text = "apple's price $99, orange's price $10" ret = re.search('.*(\$\d+).*(\$\d+)', text) # 將整個(gè)字符串提取出來(lái)括號(hào)里是分組的意思print(ret.group()) # 整個(gè)正則表達(dá)式 就是一個(gè) 大的分組,可以寫(xiě)0或者不寫(xiě) 都是可以的 print(ret.group(1)) # 第一個(gè)分組 print(ret.group(2)) # 第二個(gè)分組 print(ret.group(1, 2)) # 兩個(gè)分組 拿出來(lái) print(ret.groups()) # 所有 的子分組 都拿出來(lái)
(...)\number
# (\number)In [101]: a='WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB' In [102]: a Out[102]: 'WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB'In [103]: re.sub(r"(.)\1+",lambda x:str(len(x.group(0)))+ x.group(1),a)Out[103]: '12WB12W3B24WB'In [109]: re.sub(r"(.)\1+",lambda x:print(x),a) <_sre.SRE_Match object; span=(0, 12), match='WWWWWWWWWWWW'> <_sre.SRE_Match object; span=(13, 25), match='WWWWWWWWWWWW'> <_sre.SRE_Match object; span=(25, 28), match='BBB'> <_sre.SRE_Match object; span=(28, 52), match='WWWWWWWWWWWWWWWWWWWWWWWW'> Out[109]: 'BB'group 都是 從 1 開(kāi)始編碼
group(0) 等價(jià)于 group() 返回整個(gè) 匹配 。
groups
返回一個(gè)包含匹配的所有子組的元組,從1到模式中的所有組。這個(gè) default 參數(shù)用于沒(méi)有參與匹配的組;它默認(rèn)為 None .
關(guān)于分組的 一些實(shí)際 例子
分組的反向引用 ( 就是那個(gè) \1)
import re import requests pat="<(\w+)>(.+)<\/\1>" # 基本套路 不過(guò)對(duì)于一些復(fù)雜的 html 標(biāo)簽無(wú)法 提取 res=requests.get("http://www.baidu.com") res.encoding='utf-8' html=res.textpat=r"<(head)>(.+)</\1>" # 稍加 修改 re.findall(pat,html) # ---------------------------- # 返回結(jié)果 # [('head', #'<meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=http://s1.bdstatic.com/r/www/cache/bdorz/baidu.min.css><title>百度一下,你就知道</title>')]pat=r"<(div)\s*.*?>(.+)</\1>" # 再次修改 re.findall(pat,html) # 返回結(jié)果 # [('div', # ' <div id=head> <div class=head_wrapper> <div class=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129> </div> <form id=form name=f action=//www.baidu.com/s class=fm> <input type=hidden name=bdorz_come value=1> <input type=hidden name=ie value=utf-8> <input type=hidden name=f value=8> <input type=hidden name=rsv_bp value=1> <input type=hidden name=rsv_idx value=1> <input type=hidden name=tn value=baidu><span class="bg s_ipt_wr"><input id=kw name=wd class=s_ipt value maxlength=255 autocomplete=off autofocus></span><span class="bg s_btn_wr"><input type=submit id=su value=百度一下 class="bg s_btn"></span> </form> </div> </div> <div id=u1> <a href=http://news.baidu.com name=tj_trnews class=mnav>新聞</a> <a href=http://www.hao123.com name=tj_trhao123 class=mnav>hao123</a> <a href=http://map.baidu.com name=tj_trmap class=mnav>地圖</a> <a href=http://v.baidu.com name=tj_trvideo class=mnav>視頻</a> <a href=http://tieba.baidu.com name=tj_trtieba class=mnav>貼吧</a> <noscript> <a href=http://www.baidu.com/bdorz/login.gif?login&amp;tpl=mn&amp;u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1 name=tj_login class=lb>登錄</a> </noscript> <script>document.write(\'<a href="http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u=\'+ encodeURIComponent(window.location.href+ (window.location.search === "" ? "?" : "&")+ "bdorz_come=1")+ \'" name="tj_login" class="lb">登錄</a>\');</script> <a href=//www.baidu.com/more/ name=tj_briicon class=bri style="display: block;">更多產(chǎn)品</a> </div> </div> </div> <div id=ftCon> <div id=ftConw> <p id=lh> <a href=http://home.baidu.com>關(guān)于百度</a> <a href=http://ir.baidu.com>About Baidu</a> </p> <p id=cp>©2017 Baidu <a href=http://www.baidu.com/duty/>使用百度前必讀</a>&nbsp; <a href=http://jianyi.baidu.com/ class=cp-feedback>意見(jiàn)反饋</a> 京ICP證030173號(hào) <img src=//www.baidu.com/img/gs.gif> </p> </div> </div> ')]pat=r"<(\w+)\s*.*?>(.+)</\1>" # pat="<(\w+)>(.+)<\/\1>" 完成我在一開(kāi)始想用這個(gè)操作的事情。 re.findall(pat,html) # 返回結(jié)果 #[('html', # ' <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=http://s1.bdstatic.com/r/www/cache/bdorz/baidu.min.css><title>百度一下,你就知道</title></head> <body link=#0000cc> <div id=wrapper> <div id=head> <div class=head_wrapper> <div class=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129> </div> <form id=form name=f action=//www.baidu.com/s class=fm> <input type=hidden name=bdorz_come value=1> <input type=hidden name=ie value=utf-8> <input type=hidden name=f value=8> <input type=hidden name=rsv_bp value=1> <input type=hidden name=rsv_idx value=1> <input type=hidden name=tn value=baidu><span class="bg s_ipt_wr"><input id=kw name=wd class=s_ipt value maxlength=255 autocomplete=off autofocus></span><span class="bg s_btn_wr"><input type=submit id=su value=百度一下 class="bg s_btn"></span> </form> </div> </div> <div id=u1> <a href=http://news.baidu.com name=tj_trnews class=mnav>新聞</a> <a href=http://www.hao123.com name=tj_trhao123 class=mnav>hao123</a> <a href=http://map.baidu.com name=tj_trmap class=mnav>地圖</a> <a href=http://v.baidu.com name=tj_trvideo class=mnav>視頻</a> <a href=http://tieba.baidu.com name=tj_trtieba class=mnav>貼吧</a> <noscript> <a href=http://www.baidu.com/bdorz/login.gif?login&amp;tpl=mn&amp;u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1 name=tj_login class=lb>登錄</a> </noscript> <script>document.write(\'<a href="http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u=\'+ encodeURIComponent(window.location.href+ (window.location.search === "" ? "?" : "&")+ "bdorz_come=1")+ \'" name="tj_login" class="lb">登錄</a>\');</script> <a href=//www.baidu.com/more/ name=tj_briicon class=bri style="display: block;">更多產(chǎn)品</a> </div> </div> </div> <div id=ftCon> <div id=ftConw> <p id=lh> <a href=http://home.baidu.com>關(guān)于百度</a> <a href=http://ir.baidu.com>About Baidu</a> </p> <p id=cp>©2017 Baidu <a href=http://www.baidu.com/duty/>使用百度前必讀</a>&nbsp; <a href=http://jianyi.baidu.com/ class=cp-feedback>意見(jiàn)反饋</a> 京ICP證030173號(hào) <img src=//www.baidu.com/img/gs.gif> </p> </div> </div> </div> </body> ')]一些運(yùn)行效果
常用的 flags
re.A
re.ASCII
制作 \w , \W , \b , \B , \d , \D , \s 和 \S 只執(zhí)行ASCII匹配,而不是完全Unicode匹配。這只對(duì)Unicode 模式有意義,而對(duì)于字節(jié)模式則被忽略。對(duì)應(yīng)于內(nèi)聯(lián)標(biāo)志 (?a) .
請(qǐng)注意,為了向后兼容, re.U 標(biāo)志仍然存在(及其同義詞 re.UNICODE 及其嵌入的對(duì)應(yīng)項(xiàng) (?u) ,但在python 3中這些是多余的,因?yàn)樽址钠ヅ淠J(rèn)為Unicode(字節(jié)不允許使用Unicode匹配)。
re.DEBUG
顯示有關(guān)已編譯表達(dá)式的調(diào)試信息。沒(méi)有對(duì)應(yīng)的內(nèi)聯(lián)標(biāo)志。
re.I
re.IGNORECASE
執(zhí)行不區(qū)分大小寫(xiě)的匹配; 對(duì)應(yīng)于內(nèi)聯(lián)標(biāo)志 (?i) .
re.M
re.MULTILINE
指定時(shí),模式字符 '^' 匹配字符串的開(kāi)頭和每行的開(kāi)頭(緊跟每行換行符);以及模式字符 $ 匹配字符串的結(jié)尾和每行的結(jié)尾(緊接著每行換行符的前面)。默認(rèn)情況下, '^' 僅在字符串的開(kāi)頭匹配,并且 '$' 只在字符串的末尾,在字符串末尾的換行符(如果有)之前。對(duì)應(yīng)于內(nèi)聯(lián)標(biāo)志 (?m) .
其實(shí)一句話 就是 換行符為邊界
比如 22\n3322\n3322\n33 如果我要獲取 以某某開(kāi)頭的兩位數(shù)字字符。 以換行符為邊界。 那就是 22 33 33 33
可以理解為 行首 行尾 的概念。
而不是字符串的首尾。
如果flags 用 re.M 但是想要 獲取字符串首部 那就是 \A 需要寫(xiě)在開(kāi)頭 ,獲取字符串尾部是 \Z 需要寫(xiě)在后面
import re pat=r"(?m)^\d{2}" str_="22\n3322\n3322\n33" re.findall(pat,str_)關(guān)于 \A \Z
import re pat=r"(?m)^\A\d{2}" str_="22\n3322\n3322\n33" re.findall(pat,str_) pat=r"(?m)^\d{2}\Z" re.findall(pat,str_)re.S
re.DOTALL
使'.'特殊字符完全匹配任何字符,包括換行符;如果沒(méi)有此標(biāo)志, '.' 會(huì)匹配任何東西 除了 換行符對(duì)應(yīng)于內(nèi)聯(lián)標(biāo)志 (?s) .
re.X
re.VERBOSE
此標(biāo)志允許您編寫(xiě)看起來(lái)更好、更可讀的正則表達(dá)式,方法是允許您直觀地分隔模式的邏輯部分并添加注釋。
指定多個(gè) flags 的方式
re.I | re.M 用 | 表達(dá)符 表示 flags 被設(shè)置為了 re.I 和 re.M
或者使用內(nèi)聯(lián)的方式 (?im) 并且這個(gè) 標(biāo)志要寫(xiě)在 最開(kāi)始的位置。 否則會(huì)報(bào) 警告信息
import re str_=""" One1 oNe2 onE3 noe4 """ pat=r"^one\w+" pat1=r"(?im)one\w+" re.findall(pat,str_) re.findall(pat1,str_) re.findall(pat,str_,flags=re.I|re.M) re.findall(pat,str_,flags=re.I) re.findall(pat,str_,flags=re.M)一些不常見(jiàn)的匹配符號(hào)
(?P=name)
- (?P< name >)
- 命名的格式 (注意P是大寫(xiě)的)
- (?P=name)
- 取值的格式
對(duì)命名組的后向引用;它與先前命名組匹配的任何文本匹配 name .
<(?P<p1>\w*)><(?P<p2>\w*)>.*</(?P=p2)></(?P=p1)>
以這為 例子
import rehtml_str = "<body><h1>hahaha</h1></body>" ret = re.match(r"<(?P<p1>\w*)><(?P<p2>\w*)>.*</(?P=p2)></(?P=p1)>", html_str) print(ret.group())(?#...)
注釋;括號(hào)的內(nèi)容被忽略。
相當(dāng)于沒(méi)寫(xiě)。 就可以理解為 就是 寫(xiě)的注釋
正則 斷言匹配
斷言的組成之一是邊界。對(duì)于文本、詞或模式,邊界可以用來(lái)表明它們的起始或終止部分(如向前斷言,向后斷言以及條件表達(dá)式)。
(?=...) => 匹配 某字符跟隨某某字符 ,匹配前者。
匹配如果 ... 匹配下一個(gè),但不使用任何字符串。這叫A lookahead assertion 前瞻性斷言或者說(shuō) 先行斷言 . 例如, Isaac (?=Asimov) 將匹配 'Isaac ' 只有在后面跟著 'Asimov' .
向前斷言:例如,對(duì)于 Jack(?=Sprat),“Jack”在跟有“Sprat”的情況下才會(huì)得到匹配./Jack(?=Sprat|Frost)/ “Jack”后跟有“Sprat”或“Frost”的情況下才會(huì)得到匹配。不過(guò), 匹配結(jié)果 不包括 “Sprat”或“Frost”。
所謂的先行是指的 匹配的東西先行
條件后行。
tips: 記憶小技巧 有箭頭的斷言 條件都寫(xiě)在 前面的。
所以 都是后行。
先行斷言 匹配的模式字符寫(xiě)在 前面
后行斷言 匹配的模式字符串寫(xiě)在后面
斷言就是指定條件。 不匹配字符。
In [81]: pat=r'Isaac (?=Asimov)'In [82]: p=re.compile(pat)In [85]: p.search("Isaac Asimovv") # 可以理解為 匹配 以某字符串結(jié)尾的 字符。 Out[85]: <_sre.SRE_Match object; span=(0, 6), match='Isaac '>
(?!...)=> 匹配 某字符串 后面沒(méi)跟著某某字符。匹配前者。
匹配如果 ... 與下一個(gè)不匹配。這是一個(gè) negative lookahead assertion 否定超前斷言 向前否定斷言. 例如, Isaac (?!Asimov) 將匹配 'Isaac ' 只要后面不是 'Asimov' .
需要注意 ()里 這個(gè)是條件 是不會(huì)被匹配到的
In [69]: pat=r'Isaac (?!Asimov)' In [74]: p.search("Isaac Asimo") Out[74]: <_sre.SRE_Match object; span=(0, 6), match='Isaac '> In [76]: p.search("Isaac Asimov")# 不匹配In [77]: p.search("Isaac Asimovv")# 不匹配In [78]: p.search("Isaac aAsimovv") # 匹配 # 可以理解為 匹配 不以 某字符串 結(jié)尾的 字符 Out[78]: <_sre.SRE_Match object; span=(0, 6), match='Isaac '>(?<=...) => 匹配前面是某某字符的某字符。匹配后者
如果字符串中的當(dāng)前位置前面有匹配項(xiàng),則匹配 ... 在當(dāng)前位置結(jié)束。這叫A positive lookbehind assertion 肯定斷言 或者叫做 向后肯定斷言 .
(?<=abc)def 將在中找到匹配項(xiàng) 'abcdef' ,因?yàn)閘ookback將備份3個(gè)字符并檢查包含的模式是否匹配。
包含的模式必須只匹配某個(gè)固定長(zhǎng)度的字符串,這意味著 abc 或 a|b 是允許的,但是 a* 和 a{{3,4}} 不是
請(qǐng)注意,以正的lookbehind斷言開(kāi)頭的模式在被搜索的字符串的開(kāi)頭將不匹配;您很可能希望使用 search() 函數(shù)而不是 match() 功能:
需要注意 ()里 這個(gè)是條件 是不會(huì)被匹配到的
import re # 前面 有 abc 那么 我就 匹配 def m = re.search('(?<=abc)def', 'abcdef') # 可以理解為以某字符串開(kāi)頭的 字符 m.group(0)# 輸出 'def'# 此示例查找連字符后的單詞: # 前面有連字符 那么我就匹配后面的 這個(gè)字符 m = re.search(r'(?<=-)\w+', 'spam-egg') m.group(0)'egg'(?<!...)=> 匹配 前面不是某某字符我就匹配某字符。 匹配后者
如果字符串中的當(dāng)前位置前面沒(méi)有匹配項(xiàng),則匹配 … . 這叫A negative lookbehind assertion 向后否定斷言.
與正查找斷言類似,包含的模式必須只匹配某些固定長(zhǎng)度的字符串。
以負(fù)的lookbehind斷言開(kāi)頭的模式可能在要搜索的字符串的開(kāi)頭匹配。
需要注意 ()里 這個(gè)是條件 是不會(huì)被匹配到的
In [87]:...: import re# 前面 不是 adc 那么我就匹配后面的字符...: m = re.search('(?<!abc)def', 'abcdef') # 未匹配到任何東西 In [90]:...: import re...: m = re.search('(?<!abc)def', 'bcdef') # 可以理解為不以某某開(kāi)頭的字符 后面的字符In [91]: m.group() Out[91]: 'def'(?(id/name)yes-pattern|no-pattern)
如果給定的組 id 或 name 指向的組 有值 將嘗試 使用 yes-pattern 匹配一些字符 ,否則嘗試使用 no-pattern 匹配一些字符 。 no-pattern 是可選的,可以省略。
特殊序列包括 '\' 以及下面列表中的一個(gè)字符。如果普通字符不是一個(gè)ASCII數(shù)字或一個(gè)ASCII字母,那么得到的RE將與第二個(gè)字符匹配。例如, \$ 與 '$'匹配 .
相信 看完 這幾張圖 然后 自己實(shí)驗(yàn) 一下 所有人都能理解這是什么意思。
- pat="(\w+@\w+(?:\.\w+)+)"
- pat="(<)?(\w+@\w+(?:\.\w+)+)(?(1)>|>$)"
- s1 的分組 id為1 的 匹配了 < 說(shuō)明有值 那么match=<user@host.com 使用 yes 模式 嘗試匹配> 因?yàn)?s1是 user@host.com 所以匹配成功
- s3的分組id 為1 的 組 值為None 所以使用 no 模式 。然后 s3=user@host.com> 所以no 模式我寫(xiě)的 匹配 > 也匹配到了。
常用正則速查
/這里是正則/
js 中正則就是 寫(xiě)在 // 下劃線中的
示例(比如我要驗(yàn)證用戶名)
import re pat='^[a-z0-9_-]{3,16}$' str="你要驗(yàn)證的字符串" re.match(pat,str)如果已有的正則 不符合你的 要求
記得自己修改一下哦
| /^[a-z0-9_-]{3,16}$/ |
| /^[a-z0-9_-]{6,18}$/ |
| /^#?([a-f0-9]{6}|[a-f0-9]{3})$/ |
| /^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/ /^[a-z\d]+(\.[a-z\d]+)*@([\da-z](-[\da-z])?)+(\.{1,2}[a-z]+)+$/ |
| /^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/ |
| /((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)/ /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/ |
| /^<([a-z]+)([^<]+)*(?:>(.*)<\/\1>|\s+\/>)$/ |
| (?<!http:|\S)//.*$ |
| /^[\u2E80-\u9FFF]+$/ |
總結(jié)
以上是生活随笔為你收集整理的1_正则表达式(python)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 编译安装virtualbox 3.1.2
- 下一篇: python书籍推荐知乎-python书