正則表達式語法簡單寫法


一、元字符

  正則表達式中的特殊字符被稱作元字符,常用的元字符如下:

  .  點,匹配除換行符以外的任意字符

  \w  匹配數字、字母和下划線(可以匹配漢字)

  \s  匹配空白字符,如空格、換行符、制表符等

  \d  匹配數字

  \b  匹配單詞的開始或結束

  ^  匹配字符串的開始

  $  匹配字符串的結尾

  \(特殊)  轉義字符。如果需要匹配的內容含有元字符本身的,需要使用轉義字符進行轉義

  “.”的用法(使用python3.x進行舉例,具體的python3.x的正則表達式的用法請參考http://www.cnblogs.com/cdinc/p/5789429.html):

string='qq14717287xx@qq.com&10010/10086'
pattern=r'.com.'
item=re.search(pattern,string)
print(item.group())

  運行結果是:

.com&

  可以看到匹配的結果是com和前一個字符和后一個字符,這個就是這個“.”的作用。

  “\w”的用法:

string='qq14717287xx@qq.com&10010/10086'
pattern=r'7287\w'
item=re.search(pattern,string)
print(item.group())

  運行結果是:

7287x

  可以看到匹配的結果是“7287”后面再多加一個字母,這就是“\w”的用法。

  “\s”的用法:

string='qq14717287xx@qq.  com&10010/10086'
pattern=r'\scom'
item=re.search(pattern,string)
print(item.group())

  運行結果是:

 com

  在com前面又匹配到了一個空格

  “\d”的用法:

string='qq14717287xx@qq.  com&10010/10086'
pattern=r'qq\d'
item=re.search(pattern,string)
print(item.group())

  運行結果是:

qq1

  “\b”的用法:

string='qq14717287xx@qq.  com&10010/10086'
pattern=r'\bcom\b'
item=re.search(pattern,string)
print(item.group())

  運行結果是:

com

  將“com”作為一個單詞進行匹配。因為匹配的是單詞的開頭或者結尾,所以如果匹配的是“om\b”也可以匹配上,是com單詞的結尾,但是“\bom”則無法匹配,因為om前面有c,認為com是一個單詞,“om”並不是單詞的開始位置,所以無法匹配。

  “^”的用法:

string='qq14717287xx@qq.  com&10010/10086'
pattern=r'^qq'
item=re.search(pattern,string)
print(item.group())

  運行結果是:

qq

  匹配以“qq”開頭,所以能夠匹配上,如果是“^com”,則無法匹配上。

  “$”的用法:

string='qq14717287xx@qq.  com&10010/10086'
pattern=r'0086$'
item=re.search(pattern,string)
print(item.group())

  運行結果是:

0086

  匹配以0086結尾,能夠匹配上。填寫正則表達式的時候,$符號要放在匹配字符串或者公式的后面。

   “\”(轉移字符)的用法:

string='qq14717287xx@qq.com$10010/10086'
pattern=r'com\$'
item=re.search(pattern,string)
print(item.group())

  運行結果是:

com$

  可見本次就是純粹的查找的“com$”,而沒有將$作為元字符處理。

二、重復

  正則表達式中提供了幾種重復的方式,畢竟如果匹配三個字母使用“\w\w\w”的方式太不方便了,如果是三個還好,如果是十個、二十個呢。

  *  重復零次或者多次

  +  重復一次或者多次

  ?  重復零次或者一次

  {n}  重復n次

  {n,}  重復n次或者更多次

  {n,m}  重復n次到m次

  “*”的用法:

string='qq14717287xx@qq.com$10010/10086'
pattern=r'\w*'
item=re.search(pattern,string)
print(item.group())

  運行結果是:

qq14717287xx

   可以看到匹配到了多次字母和數字。

  “+”的用法:

string='qq14717287xx@qq.com$10010/10086'
pattern=r'\w+!*'
item=re.search(pattern,string)
print(item.group())

  運行結果是:

qq14717287xx

  結果是匹配到了多個字母、數字,因為匹配字符串中沒有“!”。如果匹配的是“\w+!+”,則無法匹配。這從另一個方面說明了“*”和“+”的區別。

  “?”的用法:

string='qq14717287xx@qq.com$10010/10086'
pattern=r'\w+@?'
item=re.findall(pattern,string)
print(item)

  運行結果是:

['qq14717287xx@', 'qq', 'com', '10010', '10086']

  可以看到,使用匹配的字符后面含有1個或沒有“@”符號

  “{n}”的用法:

string='qq14717287xx@qq.com$10010/10086'
pattern=r'\w{5}'
item=re.findall(pattern,string)
print(item)

  運行結果是:

['qq147', '17287', '10010', '10086']

  對於數字、字母重復了五次的地方進行了匹配。

  “{n,}”的用法:

string='qq14717287xx@qq.com$10010/10086'
pattern=r'\w{5,}'
item=re.findall(pattern,string)
print(item)

  運行結果是:

['qq14717287xx', '10010', '10086']

  匹配了數字、字母重復5次及以上的地方。

  “{n,m}”的用法:

string='qq14717287xx@qq.com$10010/10086'
pattern=r'\w{5,8}'
item=re.findall(pattern,string)
print(item)

  運行結果是:

['qq147172', '10010', '10086']

  可以看到,因為限定了重復次數(5-8次),所以第一個組合(qq14717287xx)被分開進行匹配。

三、特定字符查找

  1、單字查找

  查找字母、數字我們已經知道了,但是如果我們只是想查找特定字符怎么辦?比如我只想找到有沒有aeiou這幾個字母怎么辦?沒關系,那就把他們都列出來就好了,寫作[aeiou]

string='qq14717287xx@qq.com$10010/a10086'
pattern=r'.{4}[aeiou].{2}'
item=re.findall(pattern,string)
print(item)

  運行結果是:

['qq.com$', '010/a10']

  可以看到,匹配了“o”和“a”前面的四個字符和后面的兩個字符。

  列在[]中的字符只匹配是否含有其中的字符,而[]中的寫法也有很大的自由度。

  比如想匹配數字,可以不用寫為[0123456789],而是寫為[0-9],這兩個的含義是相同的。

  同理,小寫字母可以寫為[a-z],大寫字母可以寫為[A-Z],匹配英文可以寫為[a-zA-Z]

string='qq14717287XX@qq.com$10010/a10086'
pattern=r'[0-9]{5}'
item=re.findall(pattern,string)
print('匹配數字:',item)
pattern=r'[a-zA-Z]{2}'
item=re.findall(pattern,string)
print('匹配字母:',item)
pattern=r'[a-zA-Z0-9]{4}'
item=re.findall(pattern,string)
print('匹配數字和字母:',item)

  運行結果是:

匹配數字: ['14717', '10010', '10086']
匹配字母: ['qq', 'XX', 'qq', 'co']
匹配數字和字母: ['qq14', '7172', '87XX', '1001', 'a100']

  2、分組查找

  如果我們想重復多個字符應該怎么辦呢?我們可以使用小括號來指定子表達式(也叫做分組),我們也可以指定分組重復的次數。比如我想匹配一個IP地址,我們可以這樣寫:

string="This computer's IP is 192.168.0.1"
pattern=r'(\d{1,3}\.){3}\d{1,3}'
item=re.search(pattern,string)
print(item.group())

  運行結果是:

192.168.0.1

  於是我們就得到了一個IP地址(有效性不進行驗證,驗證方法比較復雜,但是網上也有,可以百度之)。

  3、反義查找

  我們已經知道幾種查找的元字符了,但是如果我們就是不想要查找那幾種字符怎么辦呢。沒關系,正則表達式還提供反義查找方式。

  \W  匹配任意非\w的字符

  \S  匹配任意非\s的字符

  \D  匹配任意非\d的字符

  \B  匹配非單詞開頭或結尾的部分

  [^q]  匹配非q字符的部分

  [^aeiou]  匹配非aeiou的部分

  “\W”的用法:

string='qq14717287xx@qq.com&10010/10086'
pattern=r'\W+.{0,3}'
item=re.findall(pattern,string)
print(item)

  運行結果是:

['@qq.', '&100', '/100']

  “\S”的用法:

string='qq14717287   xx@qq.  com&10010/10086'
pattern=r'\S+'
item=re.findall(pattern,string)
print(item)

  運行結果是:

['qq14717287', 'xx@qq.', 'com&10010/10086']

  “\D”的用法:

string='qq14717287xx@qq.com&10010/10086'
pattern=r'\D+'
item=re.findall(pattern,string)
print(item)

  運行結果是:

['qq', 'xx@qq.com&', '/']

  “\B”的用法:

string='qq14717287xx@qq.com&10010/10086'
pattern=r'.{2}\B00\B.{2}'
item=re.findall(pattern,string)
print(item)

  運行結果是:

['&10010', '/10086']

  “^”的用法:

string='qq14717287xx@qq.com&10010/10086'
pattern=r'[^7]+'
item=re.findall(pattern,string)
print(item)

  運行結果是:

['qq14', '1', '28', 'xx@qq.com&10010/10086']

  匹配非7的部分。

四、分支條件

  正則表達式也支持類似於OR的方式,使用“|”符號連接幾個表達式,只要其中一個表達式匹配上就算匹配。

  比如我們有幾個電話,既有010-12345678的固定電話方式,又有15812345678的手機方式,我們應該怎么匹配呢?

string1='010-12345678'
string2='15812345678'
pattern=r'\d{3}-\d{8}|\d{11}'
item=re.findall(pattern,string1)
print(item)
item=re.findall(pattern,string2)
print(item)

  運行結果:

['010-12345678']
['15812345678']

  可以看到,我們使用相同匹配表達式都能夠匹配到需要的內容。

  但是,需要注意的是,這種方式的匹配是有順序的。比如美國的郵政編碼是一個5位數字或者是一個用連字符連起來的9位數字,那么它的匹配表達式的寫法是:\d{5}-\d{4}|\d{5},如果順序顛倒,那么就只會匹配5個數字而不會再匹配用連字符連起來的9位數字了,因為只要能夠匹配上就不會再考慮后面的表達式了。所以使用分枝條件的時候需要注意條件的順序。

五、注釋

  在正則表達式中,我們可以使用(?#content)來使用注釋。

string='qq14717287xx@qq.com&10010/10086'
pattern=r'\D+(?#This is a comment)'
item=re.findall(pattern,string)
print(item)

  運行結果是:

['qq', 'xx@qq.com&', '/']

  可以看到,注釋內容並沒有影響匹配結果。

  我們還可以將正則表達式寫為多行,通過設置忽略多余的空白字符選項,可以將注釋寫為只是#開頭,這種方式下,#的后面至行末都被判斷為注釋。

string='qq14717287xx@qq.com&10010/10086'
pattern=r'''\D+     #This is a comment
            .{2}    #This is a comment too
            \d+     #This is also a comment'''
item=re.findall(pattern,string,re.X)
print(item)

  運行結果是:

['qq14717287', 'xx@qq.com&10010', '/10086']

六、貪婪匹配與懶惰匹配

  正則表達式默認匹配盡可能多的字符。

string='this is a demo text!'
pattern=r't.*t'
item=re.findall(pattern,string)
print(item)

  運行結果是:

['this is a demo text']

  這個表達式匹配了最長的以t開始中間沒有或多個字符再以t結尾的一個字段。這種匹配模式就被稱為貪婪模式

  但是有時候我們的需求是需要匹配盡可能少的字符,這種方式在正則表達式中被成為懶惰模式。需要匹配懶惰模式,只需要在限定符后面加入一個?就可以了。

  懶惰模式有以下幾種形式:

  *?  重復任意次,但是匹配盡可能少的字符。

  +?  重復1次或者多次,但是匹配盡可能少的字符。

  ??  重復0次或者1次,但是匹配盡可能少的字符。

  {n,m}?  重復n次到m次,但是匹配盡可能少的字符。

  {n,}?  重復n次以上,但是匹配盡可能少的字符。

  以下看一下它們的用法及匹配結果:

  “*?”:重復任意次,但是匹配盡可能少的字符。

string='this is a demo text!'
pattern=r't.*?t'
item=re.findall(pattern,string)
print(item)

  運行結果是:

['this is a demo t']

  這樣就就匹配了t和t之間最少的字符。but,為什么匹配結果不是“text”呢?因為正則表達式有一個優先級更高的規則,最先開始的匹配擁有最高優先權

  “+?”:重復1次或者多次,但是匹配盡可能少的字符。

string='this is a demo text,too!'
pattern=r'd.+o'
item=re.findall(pattern,string)
print('普通(貪婪)匹配結果:',item)
pattern=r'd.+?o'
item=re.findall(pattern,string)
print('懶惰匹配結果:',item)

  運行結果是:

普通(貪婪)匹配結果: ['demo text,too']
懶惰匹配結果: ['demo']

  “??”:重復0次或者1次,但是匹配盡可能少的字符。

string='this isi a demo text,too!'
pattern=r't.?o'
item=re.findall(pattern,string)
print('普通(貪婪)匹配結果:',item)
pattern=r't.??o'
item=re.findall(pattern,string)
print('懶惰匹配結果:',item)

  運行結果是:

普通(貪婪)匹配結果: ['too']
懶惰匹配結果: ['to']

  “{n,m}?”:重復n次到m次,但是匹配盡可能少的字符。

string='this isi a demo text,too!'
pattern=r't.{2,5}t'
item=re.findall(pattern,string)
print('普通(貪婪)匹配結果:',item)
pattern=r't.{2,5}?t'
item=re.findall(pattern,string)
print('懶惰匹配結果:',item)

  運行結果是:

普通(貪婪)匹配結果: ['text,t']
懶惰匹配結果: ['text']

  “{n,}?”重復n次以上,但是匹配盡可能少的字符。

string='this isi a demo text,too!'
pattern=r't.{1,}i'
item=re.findall(pattern,string)
print('普通(貪婪)匹配結果:',item)
pattern=r't.{1,}?i'
item=re.findall(pattern,string)
print('懶惰匹配結果:',item)

  運行結果是:

普通(貪婪)匹配結果: ['this isi']
懶惰匹配結果: ['thi']

七、分組

  有時我們給定的匹配條件很多,但是需要的卻不多。比如這個字符串“isi 1234 isi apple isi”,加入我們只想要“isi”中間的內容該怎么匹配呢?如果只用之前給的方法沒有辦法取出來,這就要說道分組了。

  分組就是將整個正則表達式分成不同的組,只獲取不同組匹配的內容。

  其中分組使用“()”來區分,括號內匹配的內容為一個組。

  示例如下:

string='qq14717287xx@qq123456.com&10010/10086'
pattern=r'(qq\d+).*?(qq\d+)'
item=re.match(pattern,string)
print('總共匹配到%s個數據。'%len(item.groups()))
for i in range(len(item.groups())+1):
    print('第%d個數據是:%s'%(i,item.group(i)))

  運行結果是:

總共匹配到2個數據。
第0個數據是:qq14717287xx@qq123456
第1個數據是:qq14717287
第2個數據是:qq123456

  可以看到,默認分組都是按照號碼自動分配。

  但是明明匹配到了兩個數據,為什么有三個顯示呢?這是因為分組中,分組0表示全部正則表達式,所以第0個數據就是'qq\d+.*?qq\d+'的匹配結果。

  有時候我們就是這么耿直,我們不想用你自動分配的號碼,我想自己給匹配的字符串命名。這也能夠實現,只要使用“(?P<name>pattern)”的方式就可以了。(以下為python3.x的實現方式,其他語言可能會有差別,但是原理相似)。

string='qq14717287xx@qq123456.com&10010/10086'
pattern=r'(?P<aaa>qq\d+).*?(?P<bbb>qq\d+)'
item=re.match(pattern,string)
print(item.group("aaa"))
print(item.group('bbb'))

  運行結果是:

qq14717287
qq123456

  但是有時我們又不想給某一個分組分配名字,連系統默認分配的號碼都不想給他,也能夠實現(至今沒有發現這種方式存在的意義-_-|||)。

string='qq14717287xx@qq123456.com&10010/10086'
pattern=r'(?P<aaa>qq\d+).*?(?:qq\d+)'
item=re.match(pattern,string)
print('總共匹配到%s個數據。'%len(item.groups()))
for i in range(len(item.groups())+1):
    print('第%d個數據是:%s'%(i,item.group(i)))

  運行結果是:

總共匹配到1個數據。
第0個數據是:qq14717287xx@qq123456
第1個數據是:qq14717287

  可以看到,這次我們並沒有匹配到第2個內容

  所以,分組的情況分為以下幾種:

  (pattern)  匹配pattern,系統自動為組分配號碼

  (?P<name>pattern)  匹配pattern,並將組命名為name

  (?:pattern)  匹配pattern,不捕獲匹配的文本,也不分配號碼

八、后向引用

  后向引用可以用來匹配與某個分組相同的部分,提供查找重復字符組的方便的方法。

  我們可以通過示例來進行了解。

string='qq14717287xx@qq14723456.com&10010/10086'
pattern=r'(qq\d+).*?(\1)'
item=re.match(pattern,string)
print('總共匹配到%s個數據。'%len(item.groups()))
for i in range(len(item.groups())+1):
    print('第%d個數據是:%s'%(i,item.group(i)))

  運行結果是:

總共匹配到2個數據。
第0個數據是:qq14717287xx@qq147
第1個數據是:qq147
第2個數據是:qq147

  其中\1表示第一個分組的內容,兩個分組相同並且符合匹配方式的部分的是"qq147",所以都匹配到了"qq147"。

  如果我們將第二個字符串換為qq123456之后會發生什么呢?

string='qq14717287xx@qq123456.com&10010/10086'
pattern=r'(qq\d+).*?(\1)'
item=re.match(pattern,string)
# item=re.findall(pattern,string)
print('總共匹配到%s個數據。'%len(item.groups()))
for i in range(len(item.groups())+1):
    print('第%d個數據是:%s'%(i,item.group(i)))

  運行結果是:

總共匹配到2個數據。
第0個數據是:qq14717287xx@qq1
第1個數據是:qq1
第2個數據是:qq1

  兩個分組相同並且符合匹配方式的部分的只有"qq1",所以只匹配到了"qq1"。

  如果已經給分組進行了命名呢?也沒有問題,只需要將代表分組號碼的"\1"換為分組名稱"?P=aaa"即可。

string='qq14717287xx@qq14723456.com&10010/10086'
pattern=r'(?P<aaa>qq\d+).*?(?P=aaa)'
item=re.match(pattern,string)
print('總共匹配到%s個數據。'%len(item.groups()))
for i in range(len(item.groups())+1):
    print('第%d個數據是:%s'%(i,item.group(i)))

  運行結果是:

總共匹配到1個數據。
第0個數據是:qq14717287xx@qq1
第1個數據是:qq1

  可以看到和之前的匹配結果相同,但是第二個分組並沒有進行捕獲,真不知道是不是一個好消息。

九、零寬斷言

  我們想要使用一些匹配規則作為位置,只匹配前面或者后面的內容,那應該怎么實現呢?這就要說道斷言了,斷言指定了一個位置。

  我們還是通過例子來看吧。

  (?=pattern)它斷言自身出現的位置的前面能匹配需要匹配的內容

string='qq14717287xx@qq123456.com&10010/10086'
pattern='\d+(?=\D+)'
item=re.findall(pattern,string)
print(item)

  運行結果是:

['14717287', '123456', '10010']

  可以看到,我們找到了不是數字的字符前面的數字。需要注意的是,斷言本身並不是匹配結果。

  (?<=pattern)它斷言自身出現的位置的后面能匹配需要匹配的內容

string='qq14717287xx@qq123456.com&10010/10086'
pattern='(?<=\d)\D+'
item=re.findall(pattern,string)
print(item)

  運行結果是:

['xx@qq', '.com&', '/']

  注意,這種方式下,\d后不能加*、+、?,因為這種方式不支持不定長度正則表達式(如果有錯誤,歡迎指正)。

  (?=pattern)它斷言需要匹配的內容后面不跟隨pattern

string='qq14717287xx@qq123456.com&10010/10086'
pattern='\d+(?!\D)'
item=re.findall(pattern,string)
print(item)

  運行結果是:

['1471728', '12345', '1001', '10086']

   (?<!pattern)它斷言需要匹配的內容前面不跟隨pattern,同樣的,這種方式下,pattern后不能加*、+、?

string='qq14717287xx@qq123456.com&10010/10086'
pattern='(?<!\D)\d+'
item=re.findall(pattern,string)
print(item)

  運行結果是:

['4717287', '23456', '0010', '0086']

十、沒有提到的東西

  雖然已經進行整理,但是肯定還有各種沒有提到的東西。

  為什么沒有提到呢?因為我沒有試出來用法啊(尷尬笑.jpg),以后如果能夠試出來怎么使用再繼續更新吧。

  如果有什么疑問或者建議請留言,或者發送我的郵箱(就是那個1471728764.qq.com啦),我會揀我會的回答的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM