正則表達式可以幫助我們更好的描述復制的文本格式,可以更好地利用它們對文本數據進行檢索、替換、提取和修改操作。
http://www.cnblogs.com/huxi/archive/2010/07/04/1771073.html
http://docs.python.org/2.7/library/re.html#module-re
1、 re入門
第一步:先要引入有關正則表達式的包:
#-*- coding: utf-8 -*- import re
第二步:使用指定的正則表達式構建一個正則表達式對象,下面正則是用來搜索長度為10的a-z的英文字母
#-*- coding: utf-8 -*- import re regex = re.compile(r'[a-z]{10}')
第三步:根據正則表達式指定數據中檢索匹配項,如果匹配IsMatch方法就會返回true
#!/usr/bin/env python26 #-*- coding:utf-8 -*- import re
regex = re.compile(r'[a-z]{10}') m1 = re.match(regex,'1234567890') m2 = re.match(regex,'abcdefghij') if m1: print "m1 match" if m2: print "m2 match"
2、三個重要的正則表達式命令
記住正則表達式最好的辦法就是記住這三樣東西:Bracket(括號)、caret(插入符號)、Dollars(美元符號)
B(括號) | 在正則表達式中有3種類型的括號: 方括號"["和花括號"{" 方括號"["內是需要匹配的字符,花括號"{"內是指定匹配字符的數量 圓括號"("則是用來分組的 |
C(插入符號) | 插入符號"^"表示正則表達式的開始 |
D(美元符號) | 美元符號"$"表示正則式的結束 |
3、驗證
3.1 驗證字符串
輸入的字符在a-g之間:[a-g]
輸入的字符在a-g之間並且長度為3:[a-g]{3}
輸入的字符在a-g之間並且最大長度為3最小長度為1:[a-g]{1,3}
如何匹配像01234567那樣的固定8位數:^[0-9]{8}$
如何驗證最小長度為3最大長度為7的數字:^[0-9]{3,7}$
如何驗證像LJI10201030那樣的發票編號,前3個是字母剩余為8位長度的數字:^[A-Z]{3}[0-9]{8}$
不區分大小寫:^[a-zA-Z]{3}[0-9]{8}$
3.2 驗證url
驗證簡單的網址URL格式嗎?
第一步:檢查是否存在www:^www.或者^[w]{3}.
第二步:域名必須是長度在1-15的英文字母:.[a-z]{1,15}
第三步:以.com或者.org結束:.(com|org)$
完整的表達式如下:
^www[.][a-z]{1,15}[.](com|org)$
3.3 驗證Email
使用BCD(3條基本語法)如何驗證email格式
第一步:email是長度在1-10的英文字母開頭,最后跟一個“@”:
^[a-z][a-zA-Z0-9]{1,9}@$
第二步:@后面是長度在1-10的英文字母,后面跟一個".":
@[a-zA-Z]{1,10}.
第三步:最后以.com或者.org結束:
.(com|org)$
最后完整表達式:
^[a-z][a-zA-Z0-9]{1,9}@[a-zA-Z]{1,10}[.](com|org)$
3.4 驗證值在0-25的數字:
第一步:個位數[0-9]
第二步: 10-19表示[0-1][0-9]
第三步:20-25表示[0-2][0-5]
分為三組,組與組之間區分方式為小括號(,組與組之間的組合方式為|
^(([0-9])|([0-1][0-9])|([0-2][0-5]))$
3.5 驗證格式為MM/DD/YYYY,YYYY/MM/DD 和DD/MM/YYYY的日期
DD/MM/YYYY:
^(([1-9]|0[1-9])|[1-2][0-9]|3[0-1])[-./]([1-9]|0[1-9]|1[0-2])[-./](1[9][0-9]|2[0][0-9][0-9])$
步驟 | 正則表達式 | 描述說明 |
先檢查DD。首先DD的長度為1-29(2月份),1-30(小月),1-31(大月) 匹配[1-9]|0[1-9] |
[1-9]|0[1-9] | 允許用戶輸入1-9或者01-09 |
再為DD添加匹配10-19 | 1[0-9] | 允許用戶輸入10-19 |
再為DD添加匹配20-29 | 2[0-9] | 允許用戶輸入20-29 |
判斷30-31 | 3[0-1] | 允許用戶輸入30-31 |
分隔符/ . -判斷 | [- . /] | 日期分割符 |
判斷MM | [1-9]|0[1-9]|1[0-2] | 允許用戶輸入1-9或者01-09以及10-12月 |
YYYY | 1[9][0-9][0-9]|2[0][0-9][0-9] | 允許用戶輸入1900-2099 |
4、字符串類
匹配一個電話區號碼:'010-84451222 01084451222 (010)84451222'
首先是一個轉義字符\(,它能出現0次或者1次?,然后是一個0,后面跟着2個數字\d{2},然后是)或者-或者空格中的一個[)- ],它出現1次或者不出現?,最后是8個數字\d{8}
完整的表達式為\(?0\d{2}[)- ]?\d{8}
#!/usr/bin/env python2.7 #-*- coding: utf8 -*- import re regex = re.compile(r'\(?0\d{2}[)-]?\d{8}') m1 = re.search(regex,'010-84451222') m2 = re.search(regex,'01084451222') m3 = re.search(regex,'(010)84451222') m4 = re.search(regex,'010-84451222 01084451222 (010)84451222') if m4 is not None: print m4.group() m5 = re.findall(regex,'010-84451222 01084451222 (010)84451222') print m5
5、正則表達式符
5.1 常用的元字符
代碼 | 說明 |
. | 匹配除換行符以外的任意字符 |
\w | 匹配字母或數字或下划線或漢字 |
\s | 匹配任意的空白符 |
\d | 匹配數字 |
\b | 匹配單詞的開始或結束 |
^ | 匹配字符串的開始 |
$ | 匹配字符串的結束 |
5.2 常用的限定符
代碼 | 說明 |
* | 重復零次或更多次 |
+ | 重復一次或更多次 |
? | 重復零次或一次 |
{n} | 重復n次 |
{n,m} | 重復n到m次 |
^:匹配字符串的開始 $:匹配字符串的結尾 \b:匹配一個單詞的邊界 \d:匹配任意數字 \D:匹配任意非數字字符 x?:匹配一個可選的x字符(它匹配1次或者0次x字符) x*:匹配0次或者多次x字符 x+:匹配1次或者多次x字符 x{n,m}:匹配x字符,至少n次,至多m次 {a|b|c}:要么匹配a,要么匹配b,要么匹配c (x):一般情況下表示一個記憶組
6、分支條件
那個表達式也能匹配010)12345678或者(022-12345678這樣的不正確的格式。要解決這個問題,需要用到分支條件。
正則表達式里的分支條件指的是有幾種規則,如果滿足其中任意一種規則都應該當成匹配,具體方法是用|把不同的規則分隔開。
0\d{2}-\d{8}|0\d{3}-\d{7}
這個表達式能匹配兩種連字號分隔的電話號碼:一種是三位區號,8位本地號碼如010-12345678,一種是4位區號,7位本地號0376-2233445
對於上個例子,更健壯的表示如下:
\(0\d{2}\)[- ]?\d{8}|0\d{2}[- ]?\d{8}
7、分組
如果想要重復多個字符又該怎么辦?
可以用小括號來指定子表達式(也叫做分組),然后就可以指定子表達式的重復次數。
(\d{1-3}.){3}\d{1-3}是一個簡單的IP地址匹配表達式。要理解這個表達式,請按下列順序分析:
\d{1,3}匹配1到3位的數字
(\d{1-3}.){3}匹配三位數字加上一個英文句號(這個整體也就是這個分組)重復三次
最后再加上一個一到三位的數字(\d{1,3})
IP地址中每個數字都不能大於255
正則表達式中並不提供關於數學的任何功能,所以只能使用冗長的分組,選擇,字符類的描述一個正確的IP地址:
(25[0-5]|2[0-4]\d|1\d{1,2}|\d.){3}25[0-5]|24\d|1\d{1,2}|\d
8、反義
常用的反義代碼 | |
代碼/語法 | 說明 |
\W | 匹配任意不是字母、數字、下划線、漢字的字符 |
\S | 匹配任意不是空白符的字符 |
\D | 匹配任意非數字的字符 |
\B | 匹配不是單詞開頭或結束的位置 |
[^x] | 匹配除了x以外的任意字符 |
[^aeiou] | 匹配除了aeiou這幾個字母以外的任意字符 |
9、后向引用
使用小括號指定一個子表達式后,匹配這個子表達式的文本可以在表達式或者其他程序中作進一步的處理。默認情況下,每個分組會自動擁有一個組號,規則是:從左向右,以分組的左括號為標志,第一個出現的分組的組號為1,第二個為2,以此類推。
*分組0對應整個正則表達式 *組號分配過程是要從左向右掃描兩遍:第一個遍只給未命名組分配,第二遍只給命名組分配——因此所有命名組的組號都大於未命名的組號 *可以使用(?:exp)這樣的語法來剝奪一個分組對組號分配的參與權
后向引用用於重復搜索前面某個分組匹配的文本。例如,\1代表分組1匹配的文本。
\b(\w+)\b\s+\1\b,可以用來匹配重復的單詞,像go ,go或者kitty kitty
這個表達式首先是一個單詞,也就是單詞開始處和結束處之間的多於一個的字母或數字(\b(\w+)\b),這個單詞會被捕獲到編號為1的分組中,然后是1個或幾個空白符(\s+),最后是分組1中捕獲的內容,也就是前面匹配的那個單詞(\1)
也可以自己指定子表達式的組名。要指定一個子表達式的組名,請使用這樣的語法:
(?<word>\w+)或者把尖括號換成'也行:(?'Word'\w+),這樣就把\w+的組名指定為Word。
要反向引用這個分組捕獲的內容,使用\k<Word>,所以上一個例子也可以寫成:
\b(?<Word>\w+)\b\s+<Word>\b
常用分組語法 | ||
分類 | 代碼/語法 | 說明 |
捕獲 | (exp) | 匹配exp,並捕獲文本到自動命名的組里 |
(?<name>exp) | 匹配exp,並捕獲文本到名稱為name的組里,也可以寫成(?'name'exp) | |
(?:exp) | 匹配exp,不捕獲匹配的文本,也不給此分組分配組號 | |
零寬斷言 | (?=exp) | 匹配exp前面的位置 |
(?<=exp) | 匹配exp后面的位置 | |
(?!exp) | 匹配后面跟的不是exp的位置 | |
(?<!exp) | 匹配前面不是exp的位置 | |
注釋 | (?#comment) | 用於提供注釋讓人閱讀 |
10、貪婪與惰性
當正則表達式中包含能接受重復的限定符,通常的行為是匹配盡可能多的字符。以這個表達式為例:a.*b,它將匹配最長的以a開始,以b結束的字符串。如果用來搜索aabab的話,它會匹配整個字符串,稱為貪婪匹配。
惰性匹配是匹配盡可能少的字符。.*?就意味着匹配任意數量的重復,但是在能使整個匹配成功的前提下使用最少的重復。
a.*?b匹配最短的,以a開始,以b結束的字符串。如果應用於aabab的話,會匹配aab和ab
懶惰限定符 | |
代碼/語法 | 說明 |
*? | 重復任意次,但盡可能少重復 |
+? | 重復1次或更多次,但盡可能少重復 |
?? | 重復0次或1次,但盡可能少重復 |
{n,m}? | 重復n到m次,但盡可能少重復 |
{n,}? | 重復n次以上,但盡可能少重復 |
11、Python之re
re有幾個重要的函數:
*match():匹配字符串開始位置
*search():掃描字符串,找到第一個位置
*findall():找到全部匹配,以列表返回
*finditer():找到全部匹配,以迭代器返回
>>> import re >>> >>> s="12abc345ab" >>> >>> m = re.match(r"\d+",s) >>> >>> m.group(),m.span() ('12', (0, 2)) >>> >>> m = re.match(r"\d{3,}",s) #從字符串開始位置進行匹配 >>> m is None True >>> >>> m = re.search(r"\d{3,}",s) >>> m.group(),m.span() ('345', (5, 8)) >>> >>> m = re.search(r"\d+",s) >>> m.group(),m.span() ('12', (0, 2))
>>> m = re.findall(r"[a-z]{2,}",s) >>> m ['abc', 'ab'] >>> >>> for m in re.finditer(r"\d+",s): ... print m.group(),m.span() ... 12 (0, 2) 345 (5, 8)
findall返回列表或者空列表,finditer和match、search一樣返回MatchObject對象。
12、MatchObject對象
match、search、finditer返回的對象——MatchObject
*group():返回匹配的完整字符串
*start():匹配的開始位置
*end():匹配的結束位置
*spance():包含起始、結束位置的元組
*groups():返回分組信息
*groupdict():返回命名分組信息
>> m = re.match(r"(\d+)\.(\d+)","24.136") >>> m.groups() ('24', '136')
>>> s
'12ab345abc'
>>> m = re.match(r"\d+(?P<letter>[ab]+)",s)
>>> m <_sre.SRE_Match object at 0x7fb848229030> >>> m.groupdict() {'letter': 'ab'}
#可以根據letter取到相關的SQL >>> m = re.match(r"(?P<letter>[ab]+)",s) >>> m is None True
#為什么這里是None,是match默認是從開始的位置進行匹配,可以設置起始位置
match:
If zero or more characters at the beginning of string match this regular expression, return a corresponding MatchObject instance. Return None if the string does not match the pattern; note that this is different from a zero-length match.
>>> pattern = re.compile("o") >>> pattern.match("dog") >>> pattern.match("dog",1) #重新設置起始位置 <_sre.SRE_Match object at 0x7fb848216718>