正則表達式-python向

正則表達式

正則的元字符

w3c的零基礎(chǔ)教程:https://www.w3cschool.cn/regexp/zoxa1pq7.html

正則表達式30分鐘入門教程:http://deerchao.net/tutorials/regex/regex.htm

微軟的正則表達式https://docs.microsoft.com/zh-cn/dotnet/standard/base-types/regular-expression-language-quick-reference

正則速查:http://www.uedsc.com/lookup-tables.html

'*','+'和'?' 表示字符重復出現(xiàn)的次數(shù),分別表示“零或更多”,“一次或更多”還有“零次或一次”舍咖。

'*','+'和'?' 相當于"{0,}"列荔,"{1,}"和"{0,1}"浸赫。

"ab*":表示一個字符串有一個a后面跟著零個或若干個b害幅。("a", "ab", "abbb",……)绘沉;
"ab+":表示一個字符串有一個a后面跟著至少一個b或者更多营搅;#貪婪匹配云挟,盡可能多的匹配
"ab?":表示一個字符串有一個a后面跟著零個或者一個b;#非貪婪匹配转质,盡可能少的匹配
"a?b+$":表示在字符串的末尾有零個或一個a跟著一個或幾個b。

"ab{2}":表示一個字符串有一個a跟著2個b("abb")帖世;
"ab{2,}":表示一個字符串有一個a跟著至少2個b休蟹;
"ab{3,5}":表示一個字符串有一個a跟著3到5個b。
"hi|hello":表示一個字符串里有"hi"或者"hello"日矫;
"(b|cd)ef":表示"bef"或"cdef"赂弓;
"(a|b)*c":表示一串"a""b"混合的字符串后面跟一個"c";

[]方括號是字符集合哪轿,表示匹配方括號中所包含的任意一個字符

中括號里的^稱為脫字符盈魁,表示不匹配集合中的字符

"a.[0-9]":表示一個字符串有一個"a"后面跟著一個任意字符和一個數(shù)字;
"^.{3}$":表示有任意三個字符的字符串(長度為3個字符)窃诉;
"[ab]":表示一個字符串有一個"a"或"b"(相當于"a|b")杨耙;
"[a-d]":表示一個字符串包含小寫的'a'到'd'中的一個(相當于"a|b|c|d"或者"[abcd]");
"^[a-zA-Z]":表示一個以字母開頭的字符串飘痛;
"[0-9]%":表示一個百分號前有一位的數(shù)字珊膜;
",[a-zA-Z0-9]$":表示一個字符串以一個逗號后面跟著一個字母或數(shù)字結(jié)束。
"%[^a-zA-Z]%"表示兩個百分號中間不應(yīng)該出現(xiàn)字母
[^good]     匹配除了good這幾個字母以外的所有字符宣脉,
[^0-9]      匹配所有的非數(shù)字字符
'''
^   行首匹配车柠,和在[]里的^不是一個意思,注意:寫在最前面塑猖,表示一個字符串的開始
$   行尾匹配竹祷,注意:寫在正則最后面,表示一個字符串的結(jié)束
.   匹配除換行符以外的任意字符
說明:下方的x羊苟,y均為假設(shè)的普通字符塑陵,n,m(非負整數(shù))践险,不是正則表達式的元字符
(xyz)   匹配小括號內(nèi)的xyz(作為一個整體去匹配)
x?      匹配0個或者1個x
x*      匹配0個或者任意多個x(.*表示匹配0個或者任意多個字符(換行符除外))
x+      匹配至少一個x
x{n,}   匹配至少n個x
x{n}    匹配確定的n個x(n是一個非負整數(shù))
x{n,m}  匹配至少n個最多m個x猿妈,注意n<=m
x|y     |表示或,匹配的是x或y

\d          匹配數(shù)字巍虫,效果同[0-9]
\D          匹配非數(shù)字字符彭则,效果同[^0-9]
\w          匹配數(shù)字,字母和下劃線占遥,效果同[0-9a-zA-Z_]
\W          匹配非數(shù)字俯抖,字母和下劃線,效果同[^0-9a-zA-Z_ ]
\s          匹配任意的空白符(空格瓦胎、回車芬萍、換行尤揣、制表、換頁)柬祠,效果同[\r\n\t\f]
\S          匹配任意的非空白符北戏,效果同[^\f\n\r\t]
'''
注意:
通常情況下?與*或者是+一起連用漫蛔,來起到一個限制貪婪匹配的作用
*與+一般情況下與“.”,代表匹配任意多個任意字符
'''
\A  匹配字符串開始嗜愈,它和^的區(qū)別是,\A只匹配整個字符串的開頭莽龟,即使在re.M模式(,flags=re.m)下也不會匹配其他行的行首
\Z  匹配字符串結(jié)束蠕嫁,它和$的區(qū)別是,\Z只匹配整個字符串的結(jié)束毯盈,即使在re.M模式下也不會匹配其它行的行尾
注意:若不指定re.M模式剃毒,則^與\A,$與\Z匹配結(jié)果相同。
\b  匹配一個單詞的邊界搂赋,也就是指單詞和空格的位置赘阀,'er\b'可以匹配never,不能匹配nerve厂镇。
    注意:當\b添加在單詞左邊的時候纤壁,它會從單詞左邊的邊界開始匹配,
        當\b添加添加單詞的右邊的時候,它會從單詞的右邊邊界開始匹配.
        若想匹配整個單詞捺信,我們需要給這個單詞左右兩邊都添加\b
\B  匹配非單詞邊界 
    #注意:當\B寫在左邊酌媒,它表示非左邊邊界開始匹配
        當\B寫在右邊,它表示非右邊邊界開始匹配
        若單詞兩邊都有\(zhòng)B,它只匹配單詞非邊界中含有字符迄靠。
'''

為了逐字表達秒咨,你必須在"^.$()|[]+?{"這些字符前*加上轉(zhuǎn)義字符\''。

請注意在方括號中掌挚,不需要轉(zhuǎn)義字符雨席。

貪婪與懶惰

當正則表達式中包含能接受重復的限定符時,通常的行為是(在使整個表達式能得到匹配的前提下)匹配盡可能多的字符吠式。

以這個表達式為例:a.b陡厘,它將會匹配最長的以a開始,以b結(jié)束的字符串特占。如果用它來搜索aabab的話糙置,它會匹配整個字符串aabab。這被稱為貪婪*匹配是目。

有時谤饭,我們更需要懶惰匹配,也就是匹配盡可能少的字符。前面給出的限定符都可以被轉(zhuǎn)化為懶惰匹配模式揉抵,只要在它后面加上一個問號?亡容。

這樣.?*就意味著匹配任意數(shù)量的重復,但是在能使整個匹配成功的前提下使用最少的重復≡┙瘢現(xiàn)在看看懶惰版的例子吧:

a.?b匹配最短的闺兢,以a開始,以b結(jié)束的字符串辟汰。如果把它應(yīng)用于aabab*的話列敲,它會匹配aab(第一到第三個字符)和ab(第四到第五個字符)。

為什么第一個匹配是aab(第一到第三個字符)而不是ab(第二到第三個字符)帖汞?簡單地說,因為正則表達式有另一條規(guī)則凑术,比懶惰/貪婪規(guī)則的優(yōu)先級更高:最先開始的匹配擁有最高的優(yōu)先權(quán)翩蘸。

代碼/語法 說明
*? 重復任意次,但盡可能少重復
+? 重復1次或更多次淮逊,但盡可能少重復
?? 重復0次或1次催首,但盡可能少重復
{n,m}? 重復n到m次,但盡可能少重復
{n,}? 重復n次以上泄鹏,但盡可能少重復

練習題

'''功能1:提壤扇巍:you...man'''
str1 = "you are a good man,you are a nice man ,you are a great man,you are a..."
print(re.findall(r"you.*?\bman\b",str1))
#\b的用法
str1 = "good man,you are a nice man ,you are a great man,you are a..."
print(re.findall(r"\bman\b",str1))  # ['man', 'man', 'man']
'''功能2:/* part1 */ /* part2 */'''
print(re.findall(r"/\*.*?\*/",r"/* part1 */ /* part2 */"))#\轉(zhuǎn)義字符給*轉(zhuǎn)義

'''功能3:判斷電話號碼是否以134開頭'''
print(re.findall("^134\d{8}$","12345678901"))
'''
功能4:判斷QQ號碼是否合法:
1.位數(shù)6~10
2.全部是數(shù)字
3.不能以0開頭
'''
^[1-9]\d{5,9}$
'''
功能5:校驗普通電話、傳真號碼:可以“+”或數(shù)字開頭备籽,可含有“-” 和 “ ”
'''
/^[+]{0,1}(\d){1,3}[ ]?([-]?((\d)|[ ]){1,12})+$/
#可以匹配的字符串如:+123 -999 999 舶治; +123-999 999 ;123 999 999 车猬;+123 999999等
'''功能6:校驗URL'''
/^http[s]{0,1}:\/\/.+$/ 
或 /^http[s]{0,1}:\/\/.{1,n}$/ (表示url串的長度為length(“https://”) + n )
'''功能7:校驗密碼:只能輸入6-20個字母霉猛、數(shù)字、下劃線'''
^(\w){6,20}$

#功能8:對用戶輸入的數(shù)據(jù)進行限制6位0或者1珠闰,若不是則重新輸入惜浅。
def test_num():
    while True:
        num = input("請輸入一位6位的中獎號碼(0/1)組成:")
        res = re.findall("^[01]{6}$", num)
        if len(res) == 1:
            return num
        else:
            print("輸入非法,請重新輸入伏嗜。坛悉。。")
            continue  
'''
功能9
1.身份證正則
2.電話號碼的正則
3.郵箱正則
封裝成一個功能模塊承绸。
'''
import re


def checkIdcard(idcard):
    Errors = ['驗證通過!', '身份證號碼位數(shù)不對!', '身份證號碼出生日期超出范圍或含有非法字符!', '身份證號碼校驗錯誤!', '身份證地區(qū)非法!']
    area = {"11": "北京", "12": "天津", "13": "河北", "14": "山西", "15": "內(nèi)蒙古", "21": "遼寧", "22": "吉林", "23": "黑龍江",
            "31": "上海",
            "32": "江蘇", "33": "浙江", "34": "安徽", "35": "福建", "36": "江西", "37": "山東", "41": "河南", "42": "湖北", "43": "湖南",
            "44": "廣東", "45": "廣西", "46": "海南", "50": "重慶", "51": "四川", "52": "貴州", "53": "云南", "54": "西藏", "61": "陜西",
            "62": "甘肅", "63": "青海", "64": "寧夏", "65": "新疆", "71": "臺灣", "81": "香港", "82": "澳門", "91": "國外"}
    idcard = str(idcard)
    idcard = idcard.strip()
    idcard_list = list(idcard)

    # 地區(qū)校驗
    key = idcard[0: 2]  # TODO: cc  地區(qū)中的鍵是否存在
    if key in area.keys():
        if (not area[(idcard)[0:2]]):
            return Errors[4]
    else:
        return Errors[4]
    # 15位身份號碼檢測

    if (len(idcard) == 15):
        if ((int(idcard[6:8]) + 1900) % 4 == 0 or (
                (int(idcard[6:8]) + 1900) % 100 == 0 and (int(idcard[6:8]) + 1900) % 4 == 0)):
            erg = re.compile(
                '[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}$')  # //測試出生日期的合法性
        else:
            ereg = re.compile(
                '[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}$')  # //測試出生日期的合法性
        if (re.match(ereg, idcard)):
            return Errors[0]
        else:
            return Errors[2]
    # 18位身份號碼檢測
    elif (len(idcard) == 18):
        # 出生日期的合法性檢查
        # 閏年月日:((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))
        # 平年月日:((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))
        if (int(idcard[6:10]) % 4 == 0 or (int(idcard[6:10]) % 100 == 0 and int(idcard[6:10]) % 4 == 0)):
            ereg = re.compile(
                '[1-9][0-9]{5}(19[0-9]{2}|20[0-9]{2})((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}[0-9Xx]$')  # //閏年出生日期的合法性正則表達式
        else:
            ereg = re.compile(
                '[1-9][0-9]{5}(19[0-9]{2}|20[0-9]{2})((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}[0-9Xx]$')  # //平年出生日期的合法性正則表達式
        # //測試出生日期的合法性
        if (re.match(ereg, idcard)):
            # //計算校驗位
            S = (int(idcard_list[0]) + int(idcard_list[10])) * 7 + (int(idcard_list[1]) + int(idcard_list[11])) * 9 + (
                        int(
                            idcard_list[2]) + int(idcard_list[12])) * 10 + (
                            int(idcard_list[3]) + int(idcard_list[13])) * 5 + (int(
                idcard_list[4]) + int(idcard_list[14])) * 8 + (int(idcard_list[5]) + int(idcard_list[15])) * 4 + (int(
                idcard_list[6]) + int(idcard_list[16])) * 2 + int(idcard_list[7]) * 1 + int(idcard_list[8]) * 6 + int(
                idcard_list[9]) * 3
            Y = S % 11
            M = "F"
            JYM = "10X98765432"
            M = JYM[Y]  # 判斷校驗位
            if (M == idcard_list[17]):  # 檢測ID的校驗位
                return Errors[0]
            else:
                return Errors[3]
        else:
            return Errors[2]
    else:
        return Errors[1]

re模塊常用函數(shù)

complie()

'''
re.compile(patten,flags=0)
參數(shù)一:正則表達式
參數(shù)二:標志位re.M
功能:返回一個編譯正則的對象
優(yōu)點:
提高效率裸影,對于常用的一些正則我們將其編譯為對象,需要正則的的時候八酒,調(diào)用此對象即可
'''
com = re.compile("^134\d{8}")
print(com.findall("1234345566676"))
print(com.findall("13455666761"))

match()

'''
re.match(patten,string,flags=0)
功能:只在字符串開始的位置進行匹配空民,匹配成功的返回一個匹配對象,匹配失敗的時候返回None
注意:這個方法并不是完全匹配,若patten匹配到最后仍有剩余字符串界轩,仍然視為匹配成功
    若想完全匹配可以在表達式的結(jié)尾添加”$“.
'''
print(re.match("134\d{8}$","1345566677711"))
print(re.match("134\d{8}","1345566677711"))

search()函數(shù)

'''
re.search(patten,string,flags=0)
功能:匹配整個字符串画饥,返回第一個匹配結(jié)果【匹配對象】
若找不到就返回None。
'''
print(re.search(r"\bgood\b","you are a good good man").group())

findall()

'''
re.findall(patten,string,flags=0)
功能:遍歷匹配浊猾,匹配整個字符串抖甘,返回所有的匹配結(jié)果【列表】.
當匹配失敗的時候,返回一個空的列表葫慎。
'''
print(re.findall("good","you are a goods good man"))

p = re.compile(r"\d+")
print(p.findall('o1n2m3k4'))

sub()

'''
re.sub(patten,repl,string,count,flags)
替換string中每一個匹配的子串后返回替換后的【新字符串】衔彻。
參數(shù)一:要匹配的字符串【舊串】
參數(shù)二:替換的字符串 【新串】
參數(shù)三:傳入的字符串
參數(shù)四:指定替換的次數(shù)【若不指定則默認為0,全部替換】
參數(shù)五:標志位 
'''
print(re.sub("\d+","\t","hello122hello222hello11113",count=2))
print(re.sub("\d+","\t","hello122hello222hello11113"))
text = "Bob is a handsome boy, he is cool, clever, and so on..."
print(re.sub(r'\s+', '-', text))

split()

'''
re.split(patten,string[,maxsplit])
功能:以指定的匹配正則的字符串來進行切片偷办,返回一個【列表】
注意:當maxsplit不指定的時候艰额,默認整個字符串全部切片。
'''
print(re.split("\d+","hello122hello222hello11113",maxsplit=2))

正則表達式修飾符 - 可選標志

正則表達式可以包含一些可選標志修飾符來控制匹配的模式椒涯。修飾符被指定為一個可選的標志柄沮。多個標志可以通過按位 OR(|) 它們來指定。如 re.I | re.M 被設(shè)置成 I 和 M 標志:

修飾符 描述
re.I 使匹配對大小寫不敏感
re.L 做本地化識別(locale-aware)匹配
re.M 多行匹配废岂,影響 ^ 和 $
re.S 使 . 匹配包括換行在內(nèi)的所有字符
re.U 根據(jù)Unicode字符集解析字符祖搓。這個標志影響 \w, \W, \b, \B.
re.X 該標志通過給予你更靈活的格式以便你將正則表達式寫得更易于理解。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末湖苞,一起剝皮案震驚了整個濱河市拯欧,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌财骨,老刑警劉巖镐作,帶你破解...
    沈念sama閱讀 211,639評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蚓再,居然都是意外死亡滑肉,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評論 3 385
  • 文/潘曉璐 我一進店門摘仅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來靶庙,“玉大人,你說我怎么就攤上這事娃属×模” “怎么了?”我有些...
    開封第一講書人閱讀 157,221評論 0 348
  • 文/不壞的土叔 我叫張陵矾端,是天一觀的道長掏击。 經(jīng)常有香客問我,道長秩铆,這世上最難降的妖魔是什么砚亭? 我笑而不...
    開封第一講書人閱讀 56,474評論 1 283
  • 正文 為了忘掉前任灯变,我火速辦了婚禮,結(jié)果婚禮上捅膘,老公的妹妹穿的比我還像新娘添祸。我一直安慰自己,他們只是感情好寻仗,可當我...
    茶點故事閱讀 65,570評論 6 386
  • 文/花漫 我一把揭開白布刃泌。 她就那樣靜靜地躺著,像睡著了一般署尤。 火紅的嫁衣襯著肌膚如雪耙替。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,816評論 1 290
  • 那天曹体,我揣著相機與錄音俗扇,去河邊找鬼。 笑死箕别,一個胖子當著我的面吹牛狐援,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播究孕,決...
    沈念sama閱讀 38,957評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼爹凹!你這毒婦竟也來了厨诸?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,718評論 0 266
  • 序言:老撾萬榮一對情侶失蹤禾酱,失蹤者是張志新(化名)和其女友劉穎微酬,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體颤陶,經(jīng)...
    沈念sama閱讀 44,176評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡颗管,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,511評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了滓走。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片垦江。...
    茶點故事閱讀 38,646評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖搅方,靈堂內(nèi)的尸體忽然破棺而出比吭,到底是詐尸還是另有隱情,我是刑警寧澤姨涡,帶...
    沈念sama閱讀 34,322評論 4 330
  • 正文 年R本政府宣布衩藤,位于F島的核電站,受9級特大地震影響涛漂,放射性物質(zhì)發(fā)生泄漏赏表。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,934評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望瓢剿。 院中可真熱鬧逢慌,春花似錦、人聲如沸跋选。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽前标。三九已至坠韩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間炼列,已是汗流浹背只搁。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留俭尖,地道東北人氢惋。 一個月前我還...
    沈念sama閱讀 46,358評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像稽犁,于是被迫代替她去往敵國和親焰望。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,514評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 正則表達式到底是什么東西已亥?字符是計算機軟件處理文字時最基本的單位熊赖,可能是字母,數(shù)字虑椎,標點符號震鹉,空格,換行符捆姜,漢字等...
    獅子挽歌閱讀 2,141評論 0 9
  • 原文:http://www.jb51.net/tools/zhengze.html 然后強迫癥如我传趾,因為我怕網(wǎng)頁哪...
    你再不來我要下雪了閱讀 834評論 1 6
  • 注:本篇文章只為方便查看,特此保留泥技,如有冒犯浆兰,敬請諒解!A闾А镊讼! 本文目標 30分鐘內(nèi)讓你明白正則表達式是什么,并對它...
    阿杰Alex閱讀 1,479評論 0 10
  • 版本:v2.3.5 (2017-6-12) 作者:deerchao 轉(zhuǎn)載請注明來源 目錄 跳過目錄 本文目標 如何...
    readilen閱讀 950評論 2 13
  • 之前看過的關(guān)于正則的一篇優(yōu)秀文章平夜,今兒上午沒事蝶棋,摘錄給大家復習、分享放下微信忽妒,耐心讀完相信我玩裙,你會有所收獲的 本文...
    simuty閱讀 1,096評論 0 1