Python3正則表示式_re模組_教程詳解_筆記_完整內容
正則表示式,用於在一大堆資料中查詢資訊,學習後有利於爬蟲資訊抓取。
“. ^ $ * + ? { } [ ] \ | ( )”是元字元(關鍵字),如要匹配原字元則需加“\”,如“\[”“\\”。為避免與轉義符(\n、\b)衝突,可在字串前加r,即 r"" 或 r'' 。
字元:
“\d”表示數字
“\D”表示非數字的字元
“\s”表示空白字元,相當於[ \t\n\r\f\v]
“\S”相當於[^ \t\n\r\f\v]
“\w”表示數字或字母
“\W”表示非數字和字母的字元
“.”表示除換行符'\n'外的所有字元,DOTALL模式下可匹配任何字元(包括'\n')
“[]”整體為一個字元,其中的內容表示"或者"關係,同時元字元全部失效。如:[12]表示'1'或'2',[a-z]表示小寫字母(包括擴充套件拉丁字母如 'é'),[A-Za-z]表示所有字母,而[^a]表示除'a'以外的所有字元,[a^]表示'a'或'^'。由於元字元失效,從而可以 '[\n]' 的方式表示回車符等轉義符,但複雜情況下仍推薦使用 r""。
以下字元都不代表實際字元,即所謂零寬度,稱為斷言:
“^”指示行的開頭,不代表實際字元,如MULTILINE模式下以“^a”去匹配“b\nab”則span=(2, 3)。若不是MULTILINE,則僅指示字串開頭。
“$”指示行的末尾。同樣需要MULTILINE
“\A”指示字串的開頭
“\Z”指示字串的末尾
“\b”指示詞邊界,即每個單詞的開頭和結尾,單詞結構中可包括數字和字母,其他字元如空格逗號可以將其分割為一個個單詞。可以指示字串開頭。可能與退格符'\b'衝突,加r或使用'\\b'。
“|”表示或者,優先順序比普通字元還低,如“phone|tele”表示"phone"或"tele"
而“()”可控制“|”的範圍,如“the (phone|tele)”
重複:
“*”表示前一個字元重複0~+inf次
“+”表示前一個字元重複1~+inf次
“?”表示前一個字元重複0或1次,可有可無
“{m}”表示前一個字元重複m次。
“{a,b}”表示前一個字元重複a~b次,同時“{,b}”表示0~b,“{a,}”表示a~+inf次。注意大括號中不可包含空格,如“{a, b}”是錯誤的,應為“{a,b}”。
以上符號預設均為貪婪模式,即匹配儘可能多的字元。如果需匹配儘可能少的字元,可在其後加上“?”符號,如“a*?”為非貪婪模式。
“()”可使重複符號作用於其括住的全部字元上,如“(br)*”指'br'重複0~+inf次
【re模組】
基本方法:
“p = re.compile(r'ab*')”編譯一個匹配器(正則),r'ab*'為匹配規則的表示式(模式)
“m = p.match('abbcabd')”在'abbcabd'中從第一個字元開始匹配,結果儲存在match物件中並返回
“m = p.search('abbcabd')”在'abbcabd'中不斷向後查詢,只返回第一個最先匹配到的內容
“listAll = p.findall('abbcabd')”在'abbcabd'中不斷向後查詢所有能匹配的內容,並將其以列表的方式返回
“iterAll = p.finditer('abbcabd')”上一種方式的迭代器版本,迭代時才查詢並返回內容
“s = m.group()”或“s = m.group(0)”獲得匹配的內容
“s = m.start()”獲得匹配內容在字串中的起始索引值,指向匹配內容的第一個字元
“s = m.end()”獲得匹配內容在字串中的終止索引值,指向匹配內容最後一個字元的後一個字元
“s = m.span()”獲得匹配內容在字串中的範圍,元組方式返回,範圍為左包含而右不包含的
“print(m)”輸出匹配的範圍和內容
分組:
在正則表示式中把需要的資訊用小括號“()”括起來,即可獲得它們,稱為分組。如:
“p = re.compile(r'\w(\w)(\w+)')”
“m = p.match('This is Python')”
之後“m.group(1)”可返回第一個分組的內容,即'h'
“m.group(2)”可返回第二個分組的內容,即'is'
以此類推
而“m.group()”或“m.group(0)”依然返回匹配到的所有內容,即 'This'
“m.groups()”可將所有分組內容以元組的方式返回,即('h', 'is')
分組編號從左到右,由內而外。如以r'\w((\w)\w+)'匹配'This is Python'則第一個分組內容為 'his',第二個為 'h',groups()得 ('his', 'h')。
“\1”可指代前面第一個分組匹配到的內容,表示“\1”這裡必須要再次出現此內容,可用於檢測雙字(疊詞)。如:
p = re.compile(r'\b(\w+)\s+\1\b') print(p.search('Paris in the the spring').group())
得:'the the'。
分組後“findall”和“finditer”只返回分組的內容,若有多個分組則將每次匹配到的各分組內容以元組的方式儲存在列表中。
更多分組:
“(?: ... )”中 ' ... ' 處輸入的表示式匹配後不會被groups()捕獲。可用於不重要資訊的重複如 r'(?:the\s?)*'。稱為非捕獲組
“(?P<gr>...)”可將此分組命名為 'gr' ,之後通過“group('gr')”可獲得此分組的內容。稱為命名組
同時“(?P=gr)”可指代前面分組名為 'gr' 匹配到的內容,表示“(?P=gr)”這裡必須要再次出現此內容。
以上兩種表示式的“P”指Python特有。
“m.groupdict()”可返回所有被命名的分組內容,分組名為鍵(key),分組內容為值(value)
“(?#…)”為註釋,可被忽略
“(?(id/name)a|b)”指如果編號為 'id' 的分組或名稱為 'name' 的命名組存在,則匹配a表示式,否則匹配b表示式
前向斷言:
“(?=…)”指此處應出現表示式 '...' 所描述的內容,如無則此次匹配失敗。匹配成功後,其自身不計入匹配內容,原因是其自身不代表實際字元,即零寬度。這被稱為前向肯定斷言。如字串 "What's that?",若以 r"What's(?=\sth)" 匹配之則得 "What's",若以 r"What's(?=\sth)\s\w+[?]$" 匹配之則得 "What's that?"。
“(?!…)”與上一種相反,指此處不應出現表示式 '...' 所描述的內容,如出現則此次匹配失敗。這被稱為前向否定斷言。可用於排除某種檔案字尾,如 r'.*[.](?!bat$)[^.]*$' 只可匹配字尾為"bat"
後向斷言:
“(?<=…)”為後向肯定斷言,與 '(?=...)' 作用基本相同,不計入匹配內容,但其自身可以代表實際字元。如字串 "It's spam-egg",若以 r"(?<=-)\w+" search之則仍得 "egg"。“(?<=…)”中不可新增重複(\s*、a{1, 4}),但可新增其他內容如 '|'
“(?<!…)”為後向否定斷言,與上一種相反,同樣不可新增重複
標誌:
可以在re.compile()中增加匹配標誌的引數,相當於對匹配方式進行設定。標誌可以疊加,在其之間需加上 '|' 按位與運算子,如:“p.compile(r'ab*, re.M|re.I)”
“re.M”設定MULTILINE模式(多行匹配模式),使 '^' 指示行的開頭, '$' 指示行的末尾。也可寫為“re.MULTILINE”
“re.I”設定IGNORECASE模式,忽略大小寫,即大寫既可匹配大寫也可匹配小寫,小寫既可匹配小寫也可匹配大寫。也可寫為“re.IGNORECASE”
“re.L”設定LOCALE模式,方便處理本地所使用的拉丁語言。比如 'é' 'ñ' 'ç' 對於西班牙語而言只有 'é' 'ñ' 是字母,但對於法語而言則只有 'é' 'ç' 是字母。未設定re.L時,Python3預設進行 Unicode 匹配,即將 'é' 'ñ' 'ç' 都識別為字母。設定後,則據地區而定。主要影響 '\w' '\W' '\b' '\B' 和大小寫忽略(re.I)。也可寫為“re.LOCALE”
“re.S”設定DOTALL模式,使 '.' 可匹配任何字元,包括 '\n'。也可寫為“re.DOTALL”
“re.A”設定ASCII模式,使預設的 Unicode 匹配變為 ASCII 匹配,影響 '\w' '\W' '\b' '\B' '\s' '\S' 的工作。也可寫為“re.ASCI”
“re.U”設定UNICODE模式,與上一個模式相反,也可寫為“re.UNICODE”
“re.X”設定VERBOSE模式,可使正則表示式更易讀。設定re.X後,表示式中所有空格都將被忽略,並且允許加入註釋,指示各部分的含義,也可寫為“re.VERBOSE”,如:
1 charref = re.compile(r""" 2 &[#] # Start of a numeric entity reference 3 ( 4 0[0-7]+ # Octal form 5 | [0-9]+ # Decimal form 6 | x[0-9a-fA-F]+ # Hexadecimal form 7 ) 8 ; # Trailing semicolon 9 """, re.VERBOSE)
若未設定re.X則寫為:
1 charref = re.compile("&#(0[0-7]+" 2 "|[0-9]+" 3 "|x[0-9a-fA-F]+);")
設定後空格需以 r'\ ' 表示。
模組級函式:
可以不編譯匹配器(正則)而直接使用相應函式匹配內容,如:
“m = match(r'ab*', 'abbcabd', re.M)”
“m = search(r'ab*', 'abbcabd', re.M)”
“listAll = findall(r'ab*', 'abbcabd', re.M)”
“iterAll = finditer(r'ab*', 'abbcabd', re.M)”
都將表示式放在第一個引數、字串在第二個引數、標誌在第三個引數即可。
正則表示式用於處理字串的re函式:
“re.split()”可以以正則表示式匹配的內容為分割符,分割字串。
如:
“p = re.compile(r'\W+')”
“listS = p.split("This is short and sweet.")”
結果為:['This', 'is', 'short', 'and', 'sweet', '']
可指定其最大分割次數,如:
“p.split("This is short and sweet.", maxsplit=2)”指split最多分割2兩次,
得:['This', 'is', 'short and sweet.']
也可寫為“p.split("This is short and sweet.", 2)”
若正則中有捕獲分組,則還將返回捕獲分組的內容,如:
“p2 = re.compile(r'(\W+)')”
“listS2 = p2.split("This is short and sweet.")”
結果為:['This', ' ', 'is', ' ', 'short', ' ', 'and', ' ', 'sweet', '.', '']
“re.sub()”可將正則在字串中匹配到的內容替換為另一個內容。
如:
“p = re.compile('(blue|white|red)')”
“s = p.sub('colour', 'blue socks and red shoes')”
結果為:'colour socks and colour shoes'
sub()同樣可指定最大替換次數,如:
“p.sub('colour', 'blue socks and red shoes', count=1)”指sub最多替換1次,
得:'colour socks and red shoes'
也可寫為“p.sub('colour', 'blue socks and red shoes', 1)”
所替換成的另一個內容中可引用匹配內容中的分組內容,可寫為 '\1' 或 '\g<1>' ,表示引用第一個分組。對於命名組 '(?P<name>...)' 還可寫為 '\g<name>' ,如:
“p = re.compile('section{ (?P<name> [^}]* ) }', re.X)”
“p.sub(r'subsection{\1}','section{First}')”
“p.sub(r'subsection{\g<1>}','section{First}')”
“p.sub(r'subsection{\g<name>}','section{First}')”
結果均為:'subsection{First}'還可為sub()傳入一個函式,sub()會將匹配到的每一個內容以match物件的方式,傳入函式中,然後將匹配的內容替換為函式的返回值。如:
“p = re.compile(r'\d+')”
“p.sub(func, 'Call 65490 for printing, 49152 for user code.')”
可依次將匹配到的 '65490'、'49152' 作為 match 物件,傳入 func 函式。
若 func = lambda m: hex(int(m.group())) ,則得:
'Call 0xffd2 for printing, 0xc000 for user code.'
此方法可將字串中的各個整數替換為16進位制數
“subn()”的用法與sub()完全相同,但還會返回替換次數,如:
“p = re.compile('(blue|white|red)')”
“s = p.subn('colour', 'blue socks and red shoes')”
結果為:('colour socks and colour shoes', 2)
更多方法/函式:
“p.fullmatch()”或“re.fullmatch()”用法與match()一樣,但要求正則與字串必須從頭到尾完全匹配,否則返回None。相當於在正則末尾加了一個 '\Z'
“p.flags()”獲得匹配器p的所有標誌,返回值可直接傳入compile()
“p.pattern()”獲得匹配器p的正則,以字串形式返回
“re.escape()”可在字串中的所有元字元前加 '\' ,避免正則轉義,如“print(re.escape('https://www.python.org'))”得 "https://www\.python\.org"
“re.purge()”可清除正則表示式的快取
“(?...)”也可用於設定標記,放在正則前。如 '(?aiLmsux)^asd&' 可為 '^asd&' 開啟 re.A ~ re.X 所有標誌。實測效果不太理想。
【例題】
1、 找出一個字串中所有的數字,其中整數用千分位形式表示,即從個位數起,每3位之間加一個逗號,比如1,000,000,小數用定點十進位制表示,並且小數點之前至少有一位數字(比如0.618中的0不可省略)。
如:'1,234.56-234.56=1,000'
返回:['1,234.56', '234.56', '1,000']
解:
1 s = r'1,234.56-234.56=1,000' 2 3 p = re.compile(r"(\d{1,3}(?:,\d{3})*(?:\.\d+)?)") 4 L = p.findall(s) 5 print(L)
參考: