正則學習(三)

Re模塊的方法 re.match函數 match嘗試從字符串的起始位置開始匹配,如果不是起始位置匹配成功的話 返回None,匹配成功的話返回一個正則匹配對象;該方法與pattern.match()方法區別在於,它不能指定匹配的區間pos和endpos兩個參數。只有pattern模式纔可以指定配置的開始、結束位置; 語法: re.match(pattern,string,flags=0) pattern 匹配的正則表達式 String 要匹配的字符串 Flags 標誌位,用於控制正則表達式的匹配方式,如:是否區分大小寫,多行匹配等等 起始位置匹配成功 >>> re.match(r"gloryroad","gloryroad") <_sre.SRE_Match object; span=(0, 9), match='gloryroad'> >>> re.match(r"gloryroad","gloryroad").group() 'gloryroad' 起始位置匹配失敗 >>> re.match(r"gloryroad","123gloryroad") re.search函數 在整個字符串中進行掃描,並返回第一個成功的匹配,匹配成功返回一個正則匹配對象,匹配失敗返回None;該方法與pattern.search()方法區別在於,它不能指定匹配的區間pos和endpos兩個參數 語法: re.search(pattern,string,flags=0) pattern 匹配的正則表達式 String 要匹配的字符串 Flags 標誌位,用於控制正則表達式的匹配方式,如:是否區分大小寫,多行匹配等等 成功匹配: >>> re.search(r"[a-z]+\d+\s+","~abc123 \n~") <_sre.SRE_Match object; span=(1, 9), match='abc123 \n'> >>> re.search(r"[a-z]+\d+\s+","~abc123 \n~").group() 'abc123 \n' >>> re.search(r"(?P<g1>[a-z])\1\1","abc") >>> re.search(r"(?P<g1>[a-z])\1\1","aaa") <_sre.SRE_Match object; span=(0, 3), match='aaa'> >>> re.search(r"(?P<g1>[a-z])\1\1","aaa").group() 'aaa' 匹配失敗: >>> re.search(r"[a-z]+\d+\s+","~abc 123 \n~").group() Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'NoneType' object has no attribute 'group' re.findall函數 獲取字符串中所有能匹配的字符串,並以列表的形式返回。 語法: re.findall(pattern,string,flags) pattern:匹配的正則表達式 string:被匹配的字符串 flags:標誌位,用於控制正則表達式的匹配方式。如是否區分大小寫、是否多行匹配等 同樣有不帶分組,一個分組,多個分組的情況,參照pattern.fiindall() 不帶分組 >>> re.findall(r"\d+[a-z]","1a2b3c4d") ['1a', '2b', '3c', '4d'] >>> import re >>> re.findall(r"\d{2}","a123 a5678") ['12', '56', '78'] 一個分組 >>> re.findall(r"(\d+)[a-z]","1a2b3c4d") ['1', '2', '3', '4'] 多個分組 >>> re.findall(r"(\d+)([a-z])","1a2b3c4d") #兩個分組 [('1', 'a'), ('2', 'b'), ('3', 'c'), ('4', 'd')] >>> re.findall(r"((\d+)([a-z]))","1a2b3c4d")#3個分組 [('1a', '1', 'a'), ('2b', '2', 'b'), ('3c', '3', 'c'), ('4d', '4', 'd')] re.finditer函數 匹配字符串中所有滿足條件的子串,返回一個迭代器,迭代器裏面的存儲的是每一個匹配結果的匹配對象,這樣可以節省空間 re.finditer(patern,string,flags) pattern:匹配的正則表達式 string:被匹配的字符串 flags:標誌位,用於控制正則表達式的匹配方式。如是否區分大小寫、是否多行匹配等 >>> for m in re.finditer(r"\w+@\w+\.\w{2,3}","[email protected] [email protected]"): ... print(m.group()) ... [email protected] [email protected] re.split函數 把需要匹配的字符串按照正則表達式匹配的結果爲分割符進行分割,並返回分割後的列表 語法: re.split(pattern,string,maxsplit,flags) pattern:匹配的正則表達式 string:被分割的字符串 maxsplit:最大的分割次數 flags:標誌位,用於控制正則表達式的匹配方式。如是否區分大小寫、是否多行匹配等 '] 不指定分割次數 >>> re.split(r"\d+\s+","a2 b3 c4") ['a', 'b', 'c4 >>> print re.split(r"\d+","one1two2three3four4") ['one', 'two', 'three', 'four', ''] 指定分割次數 >>> re.split(r"\d+\s+","a2 b3 c4",2) ['a', 'b', 'c4'] >>> re.split(r"\d+","one1tow2three3four") ['one', 'tow', 'three', 'four'] >>> re.split(r"\D+","one1tow2three3four",3) ['', '1', '2', '3four'] re.sub函數 語法: re.sub(pattern, repl, string, count=0, flags=0) 返回一個被替換後的字符串,原字符串不變 參數說明: pattern:匹配的正則表達式 repl:用於替換的字符串 string:要被替換的字符串 count:替換的次數,如果爲0表示替換所有匹配到的字串,如果是1表示替換1次等,該參數必須是非負整數,默認爲0。 flags:標誌位,用於控制正則表達式的匹配方式。如是否區分大小寫、是否多行匹配等 >>> re.sub(r"[a-z]+","XXX","ABC123ddd333",re.I) 'ABC123XXX333' >>> re.sub(r"[a-z]+","XXX","ABC123ddd333",1,re.I)#只替換一次 'XXX123ddd333' 手機號碼後四位替換成xxxx >>> re.sub(r"\d{4}$","xxxx","13510163294") '1351016xxxx' 字母去重 將字符串中連續出現的同個字母去重,如"abbbcccbba" -> "abcba" >>> re.sub(r"([a-z])(\1)+",r"\1","abbbcccbba") 'abcba' >>> re.sub(r"([a-z])(\1+)",r"\1","abbbcccbba") 'abcba' 匹配過程: ([a-z])爲一個分組,匹配一個字母,\1引用分組,匹配和前面一樣的字母 ([a-z])(\1+) 整體匹配至少兩個一樣的字母; repl 替換字符串 爲函數 import re def multiply(m): # 將分組0的值轉成整型 v = int(m.group(0))#匹配對象調用group()得到匹配的數字 # 將分組0的整型值乘以2,然後返回 return str(v * 2) # 使用multiply方法作爲第二個參數,根據正則表達式對象搜索匹配每個數字得到的匹配對象作爲參數傳入multiply函數,處理後將返回結果替換爲相應字符串 result = re.sub("\d+", multiply, "10 20 30 40 50") print result 執行結果: re.subn函數 返回匹配內容和匹配次數的元組 語法: re.subn(pattern, repl, string, count=0, flags=0) pattern:匹配的正則表達式 repl:用於替換的字符串 string:要被替換的字符串 count:替換的次數,如果爲0表示替換所有匹配到的字串,如果是1表示替換1次等,該參數必須是非負整數,默認爲0。 flags:標誌位,用於控制正則表達式的匹配方式。如是否區分大小寫、是否多行匹配等 >>> re.subn(r"\d+","X","1A2B3C") ('XAXBXC', 3) 正則匹配對象的屬性和方法 pos屬性 該屬性表示文本中正則表達式開始搜索的索引。值與Pattern.match()和Pattern.seach()方法中的開始位置相同 >>> m = re.match(r"\d+","1b2c3") >>> m.pos 0 >>> m = re.search(r"\d+","a1b2c3") >>> m.pos 0 endpos屬性 該屬性表示文本中正則表達式結束搜索的索引。值與Pattern.match()和Pattern.seach()方法中的開始位置相同 >>> m = re.match(r"\d+","1b2c3") >>> m.endpos 5 >>> m = re.search(r"\d+","1b2c3") >>> m.endpos 5 lastindex屬性 該屬性表示最後一個被捕獲的分組索引從1開始。如果沒有被捕獲的分組,將爲None。 >>> m = re.search(r"(\d+).*(!)","1a2b3c!") >>> print m.lastindex 2 lastgroup屬性 該屬性表示最後一個被捕獲的分組別名。如果這個分組沒有別名或者沒有被捕獲的分組,將爲None >>> m = re.match(r'(\w+)! (\w+)(?P<sign>.*)', 'Hi! gloryroad!') >>> print m.lastgroup Sign group([group1, ...]) 方法 獲得一個或多個分組截獲的字符串;指定多個參數時將以元組形式返回。group1可以使用編號也可以使用別名;編號0代表匹配的整個子串;默認返回group(0);沒有截獲字符串的組返回None;截獲了多次的則返回最後一次截獲的子串。 >>> m = re.search(r"(\d+)([a-z]+)","1one2two3three4four") >>> m.group(0) '1one' >>> m.group(1) '1' >>> m.group(2) 'one' >>> m.group(1,2) ('1', 'one') >>> m.group(1,1,2)#指定多個分組編號返回匹配內容的元組 ('1', '1', 'one') 分組嵌套 >>> m = re.search(r"(a(b)c)","abcdefg") >>> m.group() 'abc' >>> m.group(1)#最外層分組編號是1 'abc' >>> m.group(2) 'b' >>> m.group(1,2) ('abc', 'b') >>> m.group(1,2,1) ('abc', 'b', 'abc') groups([default=None])方法 返回一個元組,元組內容是每個分組匹配的內容,相當於調用group(1,2,…last) >>> m = re.search(r"(a(b)c)d","abcdefg") >>> m.groups()#這個有括號 ('abc', 'b') Start方法 返回指定的組截獲的子串在string中的起始索引(子串第一個字符的索引)。默認爲第0組。 >>> m = re.search(r"\d+","aaddfs5") >>> m.start() 6 >>> m = re.search(r"(a(b)c)","abcdefg") >>> m.start() 0 end方法 返回指定的組截獲的子串在string中的結束索引(子串最後一個字符的索引)。group默認值爲0 >>> m = re.search(r"\d+","ab123cd") >>> m.start() 2 >>> m.end() 5 >>> m <_sre.SRE_Match object; span=(2, 5), match='123'> span方法 該方法表示以元組的形式返回 (start(group), end(group)),即某個分組的匹配文字內容在被匹配字符串的開始索引位置和結束索引位置 >>> m = re.search(r"\d+","ab123cd") >>> m.start() 2 >>> m.end() 5 >>> m.span() (2, 5) expand(template)方法 將匹配到的分組代入template中然後返回。template中可以使用\id或\g<id>、\g<name> 引用分組,但不能使用編號0。\id與\g<id>是等價的;但\10將被認爲是第10個分組,如果你想表達\1之後是字符'0',只能使用\g<1>0。 >>> m = re.search(r"(\w+)!\s(\w+)\s(\w+)","HMan! gloryroad train") >>> m.group() 'HMan! gloryroad train' >>> m.expand(r"result: \3 \2 \1") 'result: train gloryroad HMan' >>> m.expand(r"result: \g<1> \g<2> \g<1>") 'result: HMan gloryroad HMan' groupdict([default=None])方法 該函數的作用是,將所有匹配到並且指定了別名的分組,以別名爲key,匹配到的字串爲value,存於字典中,然後返回這個字典。如果表達式中未設置別名分組,就會返回一個空字典 >>> m = re.match(r"(?P<group1>.*)is(?P<group2>.*)",line) >>> m.group() 'This is the last one' >>> m.groups() ('This ', ' the last one') >>> m.groupdict() {'group1': 'This ', 'group2': ' the last one'} .* 正則的貪婪性 >>> s = ".*g3jl" >>> res = re.match(r".*",s).group() >>> res '.*g3jl' 點(.)表示匹配除換行符以外的任意一個字符,星號(*)表示匹配前面一個字符0次或多次,這兩符號一起使用表示匹配除換行符以爲的任意多個字符,也就是說點星(.*)組合時,它們會儘可能多的去匹配滿足條件的字符,這就是點星(.*)的貪婪性,所以就會出現上面的結果 只有當正則表達式中要匹配的字符數小於等於原字符串中的字符數時,纔有可能匹配出結果。並且 “.*” 在匹配的過程中會回溯,先匹配0次,如果整個表達式能匹配成功,再匹配一次,如果還是能匹配,那就匹配兩次,這樣一次次試下去,直到不能匹配成功時,返回最近一次匹配成功的結果,這就是”.*”的貪婪性 >>> line = "this a134gwordgtest" >>> m = re.match(r".*a.*g",line) #.*g匹配134g後還會取匹配wordg >>> m.group() 'this a134gwordg' >>> m = re.match(r".*a.*?g",line)#加?後只匹配一次 >>> m.group() 'this a134g' 正則表達式—修飾符 re.I 全寫(re.IGNORECASE),表示使匹配時,忽略大小寫 re.L 全寫(re.LOCALE),使預定字符類 \w \W \b \B \s \S 取決於當前區域設定 re.M 全寫(re.MULTILINE),多行匹配,影響 ^ 和 $的行爲 re.S 全寫(re.DOTALL),使點(.)匹配包括換行在內的所有字符 re.U 全寫(re.UNICODE),根據Unicode字符集解析字符。這個標誌影響\w \W \b \B \s \S \d \D re.X 全寫(re.VERBOSE),該標誌通過給予你更靈活的格式以便你將正則表達式寫得更易於理解。詳細模式。這個模式下正則表達式可以是多行,忽略空白字符,並可以加入註釋 re.I 忽略大小寫匹配 編譯模式 >>> pattern = re.compile(r"[a-z]+",re.I) >>> pattern.match("AbC123") <_sre.SRE_Match object; span=(0, 3), match='AbC'> >>> pattern.match("AbC123").group() 'AbC' 直接匹配模式 >>> re.match(r"[a-z]+","XYZ12",re.I) <_sre.SRE_Match object; span=(0, 3), match='XYZ'> >>> re.match(r"[a-z]+","XYZ12",re.I).group() 'XYZ' re.M 多行匹配,影響 ^ 和 $的行爲 未使用re.M匹配多行文字最後一行的結尾 ,會把字符串當成一個整體來看待 >>> s = """ ... 123 abc ... 456 xyz ... 789 ABC ... """ >>> re.search(r"[a-zA-Z]+$",s).group() 'ABC' 使用re.M,會匹配多行文字的每行結尾 >>> re.search(r"[a-zA-Z]+$",s,re.M).group() 'abc' #因爲使用的search,在第一行結尾找到就不會繼續匹配了,所以只輸出abc #不使用re.M只會匹配多行內容最後一行的結尾 >>> re.findall(r"[a-zA-Z]+$",s) ['ABC'] #使用re.M可以匹配多行內容每一行的結尾 >>> re.findall(r"[a-zA-Z]+$",s,re.M) ['abc', 'xyz', 'ABC'] #此處使用的findall所以會依次匹配每行的結尾,所以輸出了每行的匹配字符 re.I | re.M結合使用 import re p = re.compile(r'^.*[a-z]+$', re.I|re.M) string = """I am a Boy Your a beautiful Girl Right""" matchResult = p.search(string) if matchResult: print matchResult.group() else: print "no string found!" print p.findall(string) #這個對應結果第二行 執行結果: re.S 使點(.)匹配包括換行在內的所有字符 >>> re.findall(r".","a \n bc",re.S) ['a', ' ', '\n', ' ', 'b', 'c'] re.X 此標誌允許您編寫正則表達式,看起來更好。在模式中的空白將被忽略,除非當在字符類或者前面非轉義反斜槓,和,當一條線包含一個'#'既不在字符類中或由非轉義反斜槓,從最左側的所有字符之前,這種'#'通過行末尾將被忽略 以下兩個正則表達式匹配的字符是一樣的 a = re.compile(r"""\d + # the integral part \. # the decimal point \d * # some fractional digits""", re.X) b = re.compile(r"\d+\.\d*") >>> s = "ab 12 _ AB.cd.com" >>> p = re.compile(r""" ... \w+ ... \s+ ... \d+ ... \s+ ... \w+ ... \s+ ... .*#匹配任意多個字符 ... """,re.S|re.X) >>> p.match(s) <_sre.SRE_Match object; span=(0, 17), match='ab 12 _ AB.cd.com'> >>> p.match(s).group() 'ab 12 _ AB.cd.com' 分組 無名分組 分組就是用一對圓括號“()”括起來的正則表達式,匹配出的內容就表示一個分組。需要注意的是,有一個隱含的全局分組(就是索引號爲0的分組),就是整個正則表達式匹配的結果。 s = u'<div><a href="https://support.google.com/chrome/?p=ui_hotword_search" target="_blank">更多</a><p>dfsl</p></div>' print re.search(r"<a.*>(.*)</a>",s).group(1) 命名分組 命名分組就是給具體有默認分組編號的組另外再起一個別名,方便以後的引用。 命令分組的語法格式如下: (?P<name>正則表達式) 語法格式中的字符P必須是大寫的“P”,name是一個合法的標識符,表示分組的別名 >>> s = "ip='230.192.168.78',version='1.0.0'" >>> m = re.search(r"(?P<ip>\d+\.\d+\.\d+\.\d+)",s) #括號定義了一個分組,?P<ip>定義分組別名爲ip >>> print m.group() 230.192.168.78 >>> print m.group("ip")#此處可以因爲分組別名ip,要加引號 230.192.168.78 多個命名分組 >>> s = "phone,number,15817934235" >>> m = re.match(r"(?P<first>\w+),(?P<second>\w+),(?P<third>\d+)",s) >>> m.group() 'phone,number,15817934235' >>> m.group(1) 'phone' >>> m.group(2) 'number' >>> m.group(3) '15817934235' >>> m.group("first")#取名爲first分組的組 'phone' >>> m.group("second") 'number' >>> m.group("third") '15817934235' 後向引用(就是引用分組) 正則表示式中,放在圓括號“()”中的表示是一個分組。然後我們就可以對整個組使用一些正則操作,例如重複操作符。 要注意的是,只有圓括號“()”才能用於形成分組,“ ”用於定義字符串,而“{}”用於定義重複操作。 當用“()”定義了一個正則表達式分組後,正則引擎就會把匹配的組按照順序進行編號,然後存入緩存中。這樣我們就可以在後面對已經匹配過的內容進行引用,這就叫後向引用。 後向引用的語法: 1、通過索引引用 \數字 \1表示引用第一個分組,\2引用第二個分組,以此類推,\n引用第n個組,而\0則表示引用整個被匹配的正則表達式本身。 2、通過命名分組名進行引用(如果有的話) (?P=name) 字符P必須是大寫的P,name表示命名分組的分組名。 注意: 這些引用都必須是在正則表達式中才有效,用於匹配一些重複的字符串。 通過分組編號進行引用 >>> s = 'aaa111aaatestaaa >>> m = re.match(r"(\w+)\d+(\1)\w+(\1)",s) >>> m <_sre.SRE_Match object at 0x0000000002573588> >>> m.group() 'aaa111aaatestaaa' >>> m.groups() ('aaa', 'aaa', 'aaa') >>> m.group(1) 'aaa' >>> m.group(2) 'aaa' >>> m.group(3) 'aaa' 通過分組名進行引用 >>> s = 'aaa111aaatestaaa >>> m = re.match(r"(?P<first>a{3})\d+(?P=first)\w+(?P=first)",s) >>> m.group() 'aaa111aaatestaaa' >>> m.group("first") 'aaa' >>> m.groups() ('aaa',) 示例2: >>> re.search(r"\d+(?P<xx>[a-z]+)\s+(?P=xx)","12abc abc").group("xx") 'abc' ?P=xx 不是等於[a-z]+,而是等於前面分組匹配到的內容 需要注意的是:後面的(?P=XX)只是分組1即(?P<XX>[a-z]+)的引用,並不是分組2,?P=xx 不是等於[a-z]+,而是等於前面分組匹配到的內容,引用分組匹配的內容必須要與分組1的內容完全相同,否則匹配不到; 替換分組 >>> s = 'abc.xyz' >>> re.sub(r"(.*)\.(.*)",r"\2.\1",s) 'xyz.abc' >>> re.sub(r"(\w+).(\w+)",r"\2.\1",s) 'xyz.abc' 擴展表示法 前向肯定(?<=pattern) 前向肯定斷言表示你希望匹配的字符串前面是pattern匹配的內容時,才匹配字符串,但是不輸出前向肯定表達式匹配的內容;前向肯定表達式放在需要匹配字符串正則表達式前面 前向肯定斷言括號中的正則表達式必須是能確定長度的正則表達式,比如\w{3},而不能寫成\w*或者\w+或者\w?等這種不能確定個數的正則模式符 只有當abc前面是兩個數字才匹配 >>> re.search(r"(?<=\d{2})abc","1abc 45abc").group()#abc在括號外 'abc' >>> re.search(r"(?<=\d{2})abc","1abc 45abc") <_sre.SRE_Match object; span=(7, 10), match='abc'> #2處的數字只能是固定的數,不能是+等數量詞 只有當前面是兩個數字時候才匹配 >>> re.search(r"(?<=\d{2})\w+","1abc34xyz") <_sre.SRE_Match object; span=(6, 9), match='xyz'> >>> re.search(r"(?<=\d{2})\w+","1abc34xyz").group() 'xyz' >>> re.findall(r"(?<=\d{2})\w+","1abc34xyz")#abc前面只有一個數字,不匹配 ['xyz'] 只有當前面是一個大寫字母時候才匹配多個數字 >>> re.search(r"(?<=[A-Z])\d+","a123A78 llldd").group() '78' 前向否定(?<!pattern) 前向否定斷言表示你希望匹配的字符串前面不是pattern匹配的內容時,才匹配字符串,但是不輸出前向否定表達式匹配的內容, 前面不是兩個數字才匹配,所以只匹配了abc >>> re.search(r"(?<!\d{2})[a-z]+","12a XYZ",re.I).group() 'XYZ' >>> re.search(r"(?<!\d{2})[a-z]+","13a2abc").group() 'abc' 前面不是一個小寫字母的才匹配多個數字 >>> re.findall(r"(?<![a-z])\d+","a123X456 ...") ['23', '456'] >>> re.findall(r"(?<![a-z])\d+","a23 4@4") ['3', '4', '4'] >>> re.search(r"(?<![a-z])\d+","a23 4@4").group() '3' 後項肯定(?=pattern) 後向肯定斷言表示你希望匹配的字符串後面是pattern匹配的內容時,才匹配字符串,但是不輸出後向肯定表達式匹配的內容;後向肯定表達式需要放在需匹配正則表達式後面 後面是數字才匹配 >>> re.search(r"[a-z](?=\d+)","a1 b c35").group() 'a' >>> re.findall(r"[a-z](?=\d+)","a1 b c35 kk") ['a', 'c'] 一個密碼匹配的示例: #至少包含6個字符,至少一個字母、一個數字,只能包含字母數字 import re def check_password(passwd): if re.match(r'^(?=.*[A-Za-z])(?=.*[0-9])[A-Za-z0-9]{6,}$',passwd): print ("password %s strong" %passwd) else: print ("password %s is weak" %passwd) check_password("dkslfkj1") check_password("abc") check_password("123") check_password("1233abc") check_password("abc123") – ?=表示匹配表達式 後項否定(?!pattern) 後向肯定斷言表示你希望匹配的字符串後面不是pattern匹配的內容時,才匹配字符串,但是不輸出後向否定表達式匹配的內容;後向否定表達式需要放在需匹配正則表達式後面 後面不是數字匹配 >>> re.search(r"[a-z]+(?!\d+)","abc12 xyz") <_sre.SRE_Match object; span=(0, 2), match='ab'> >>> re.findall(r"[a-z]+(?!\d+)","abc12 xyz") ['ab', 'xyz'] >>> re.search(r"\w+(?!\d+)","abc123 XYZ").group() 'abc123' 之所以輸出abc123,而不是abc是因爲前面的+是貪婪式的,會儘可能多的匹配 後面不是5的匹配 >>> re.search(r"[A-Z]{3}(?!5)","ABC5XYZ1ZZZ4").group() 'XYZ' >>> re.findall(r"[A-Z]{3}(?!5)","ABC5XYZ1ZZZ4") ['XYZ', 'ZZZ'] 注意: 前向肯定與前向否定匹配規則後面的量詞只能用指定次數{n},不能用*、+、?、{m,n}等未明確次數的規則; 但是後向肯定與後向否定匹配跪着後面的量詞可以用指定次數{n},也可以用*、+、?、{m,n}等未明確次數的規則; 示例: >>> re.findall(r"(?m)^\s+(?!noreply|postmaster)(\w+)", ... """ ... [email protected] ... [email protected] ... [email protected] ... [email protected] ... [email protected] ... """ ... ) ['sale', 'eng', 'admin'] Findall只包含一個分組,只返回分組的匹配內容 (?m)表示多行匹配,每一行都會匹配 ^\s+ 表示匹配開頭多個空格 (?!noreply|postmaster) 表示不是noreply 、postmaster才匹配 (?iLmsux) 忽略大小寫 >>> re.search(r"(?i)[a-z]+","123ABCa").group() 'ABCa' .匹配\n換行 >>> re.match(r"(?s)\w+.\d+","abc\n123").group() 'abc\n123' 多行匹配模式 >>> re.findall(r"(?m)[a-z]+","abc\nxyz\n123") ['abc', 'xyz'] 忽略空白、註釋 (?:...)非捕獲模式 >>> re.findall(r"a(?:\d+)b.+a(?:\d+)b", "a23b\na34b", re.S) ['a23b\na34b']#由於此處使用非捕獲模式,所以不會返回列表,而是返回匹配 >>> re.findall(r"a(\d+)b.+a(\d+)b", "a23b\na34b", re.S)#多個括號,返回一個列表 [('23', '34')] 示例: 在下面的string中匹配到'asd'的多個重複'asdasdasdasdasdasdasd'而不是單個'asd' string='asdasdasdasdasdasdasddasfdhgasghsd' >>> string = 'asdasdasdasdasdasdasddasfdhgasghsd' >>> print(re.findall(r'((?:asd)+)', string)) ['asdasdasdasdasdasdasd'] #(?:asd)+ 是正則的一種不存分組的語法, 它具有2個用途, 將`asd`看成一個樣式整體, 所以當我們用+時, 就能代表多個asd # () 最外層的括號就是將匹配的結果存入分組, 與上面不同的就是, 少了`?:`, 因爲沒有這個, 所以它能存到分組 # 所以整體的結果就是: 將多個asd匹配, 並存入分組, 然後在re.findall的結果就能看到了 特殊字符的使用 \b匹配單詞的邊界 >>> re.findall(r"\b[a-zA-Z]+\b","i am a good boy") ['i', 'am', 'a', 'good', 'boy'] \B匹配非單詞邊界 >>> re.search(r"\Bthe\B","abthecd").group() 'the' IP匹配正則 pattern = re.compile(r'^(([1-9]|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]).){3}([1-9]|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])$') 密碼匹配規則: 密碼強度正則表達式 – 必須包含大寫字母,小寫字母和數字,至少8個字符等 需要一個密碼強度正則表達式在用戶註冊時校驗用戶密碼強度:密碼至少8個字符,包括1個大寫字母,1個小寫字母和1個數字或特殊字符,例如#,?,!。網上搜索了一些解決方案分享給大家。 方案一 至少8-16個字符,至少1個大寫字母,1個小寫字母和1個數字,其他可以是任意字符: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[^]{8,16}$/ 或者: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[\s\S]{8,16}$/ 其中 [\s\S] 中的\s空白符,\S非空白符,所以[\s\S]是任意字符。也可以用 [\d\D]、[\w\W]來表示。 至少8個字符,至少1個大寫字母,1個小寫字母和1個數字,不能包含特殊字符(非數字字母): ^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,}$ 至少8個字符,至少1個字母,1個數字和1個特殊字符: ^(?=.*[A-Za-z])(?=.*\d)(?=.*[$@$!%*#?&])[A-Za-z\d$@$!%*#?&]{8,}$ 至少8個字符,至少1個大寫字母,1個小寫字母和1個數字: ^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$ 至少8個字符,至少1個大寫字母,1個小寫字母,1個數字和1個特殊字符: ^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$@$!%*?&])[A-Za-z\d$@$!%*?&]{8,} 最少8個最多十個字符,至少1個大寫字母,1個小寫字母,1個數字和1個特殊字符: ^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$@$!%*?&])[A-Za-z\d$@$!%*?&]{8,10} 方案二 還有,你可以使用這個正則表達式: ^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,}$ 這個正則表達式將強制執行這些規則: 至少1個大寫字母English letter,(?=.*?[A-Z]) 至少1個小寫英文字母,(?=.*?[a-z]) 至少1位數字,(?=.*?[0-9]) 至少有1個特殊字符,(?=.*?[#?!@$%^&*-]) 最小8個長度.{8,} 方案三 正則表達式沒有AND運算符,所以編寫正則表達式與有效密碼匹配是非常困難的,當有效性被某些東西和其他東西等定義時… 但是,正則表達式確實有1個OR運算符,所以只需應用DeMorgan的定理,並編寫1個與無效密碼相匹配的正則表達式: 任何少於8個字符或任何沒有數字或任何沒有大寫字母或任何沒有小寫字母或任何沒有特殊字符的任何東西。 所以:^(.{0,7}|[^0-9]*|[^A-Z]*|[^a-z]*|[a-zA-Z0-9]*)$,如果有什麼匹配的話,這是1個無效的密碼。 方案四 由於特殊字符僅限於鍵盤中的特殊字符,因此可用於任何特殊字符: ^(?=.*?[A-Z])(?=(.*[a-z]){1,})(?=(.*[\d]){1,})(?=(.*[\W]){1,})(?!.*\s).{8,}$ 這個正則表達式將強制執行這些規則: – 至少1個大寫英文字母 – 至少1個小寫英文字母 – 至少1位數字 – 至少1個特殊字符 – 最少8個長度 方案五 根據我的情況,我遇到了最受歡迎的答案。例如,我的驗證失敗,其中包含;或[等字符。我對 white-listing 我的特殊字符不感興趣,所以我用[^\w\s]作爲測試 – 簡單地把非字符(包括數字)和非空格字符放在一起。總而言之,這是對我有用的 至少8字符 至少1數字字符 至少1小寫字母 至少1大寫字母 至少1特殊字符/^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[^\w\s]).{8,}$/ 簡單演示涵蓋各種情況 方案六 導入JavaScript文件jquery.validate.min.js。 您可以使用此方法: JavaScript 代碼: $.validator.addMethod("pwcheck", function (value) {return /[\@\#\$\%\^\&\*\(\)\_\+\!]/.test(value) && /[a-z]/.test(value) && /[0-9]/.test(value) && /[A-Z]/.test(value) }); 至少1個大寫英文字母 至少1個小寫英文字母 至少1位數字 至少1個特殊字符 方案七 嘗試這個: – 最少6個字符 – 至少有1個大寫字符 – 至少1個小寫字符 – 至少1個特殊字符 表達式: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$@$!%*?&.])[A-Za-z\d$@$!%*?&.]{6, 20}/ 可選特殊字符: 至少1個特殊字符 至少1個數字 特殊字符是可選的 最少6個字符,最多16個字符 表達式: /^(?=.*\d)(?=.*[a-zA-Z]).{6,20}$/ 如果不需要最小和最大條件,則刪除.{6, 16} – 6是最小字符數限制 – 20是最大字符限制 – ?=表示匹配表達式 練習: 1 找出一個字符串中是否有連續的5個數字 >>> re.search(r"\d{5}","a77788b").group() '77788' 2 找出一個字符串中的連續5個數字,要求數字前後必須是非數字 >>> re.search(r"\D\d{5}\D|^\d{5}\D|\D\d{5}|^\d{5}$","77788").group() '77788' >>> re.search(r"\D\d{5}\D|^\d{5}\D|\D\d{5}|^\d{5}$","77788").group() '77788' >>> re.search(r"\D\d{5}\D|^\d{5}\D|\D\d{5}|^\d{5}$","a77788").group() 'a77788' >>> re.search(r"\D\d{5}\D|^\d{5}\D|\D\d{5}|^\d{5}$","77788b").group() '77788b' >>> re.search(r"\D\d{5}\D|^\d{5}\D|\D\d{5}|^\d{5}$","a77788b").group() 'a77788b' 3、統計一個文件的單詞數量 >>> with open("e:\\python\\4.txt") as file_obj: ... content = file_obj.read() ... word_list = re.findall(r"\b[a-zA-Z]+\b",content) ... print(len(word_list)) ... 40 4、把a1b23c4d非字符內容拼成一個字符串 >>> "".join(re.findall(r"\d+","a1b23c4d")) '1234' 5、取最後一個字母 >>> re.findall(r"[a-zA-Z]","ab23agdf")[-1] 'f' 6、找出一個字符串中的所有數字 >>> re.findall(r"\d+","1df3dd55d55") ['1', '3', '55', '55'] 7、把一個字符串中的所有字母找出並拼成一個字符串 >>> "".join(re.findall(r"[a-z]","1df3dd55d55",re.I)) 'dfddd' 8、輸出句子中的所有單詞 >>> re.findall(r"\b[a-zA-Z]+\b","i will a strong man") ['i', 'will', 'a', 'strong', 'man'] 9、匹配字符串裏面的字典 str = """ var localCity = [{ provinceCode: "110000", cityCode: "110100", text: "北京", dpt: '20127', carNo: '京A', pName: '北京市', cName: '北京市' }, { provinceCode: "310000", cityCode: "310100", text: "上海", dpt: '2022003', carNo: '滬A', pName: '上海市', cName: '上海市' }] """ >>> re.findall(r"{.*?}",str,re.S|re.M)#因爲有換行所以點(.)要匹配\n,並且要多行模式匹配,?抑制.*匹配後面的} ['{\nprovinceCode: "110000",\ncityCode: "110100",\ntext: "北京",\ndpt: \'20127\',\ncarNo: \'京A\',\npName: \'北京市\',\ncName: \'北京市\'\n},\n{\nprovinceCode: "310000",\ncityCode: "310100",\ntext: " 上海",\ndpt: \'2022003\',\ncarNo: \'滬A\',\npName: \'上海市\',\ncName: \'上海市\'\n}'] 10、找出字符中的最大數字 >>> s = "1dsf343d9988" #findall 全局匹配,然後找最大值 >>> max([int(num) for num in re.findall(r"\d+",s)]) 9988 #findall全局匹配後,排序後,找最大值 >>> sorted([int(num) for num in re.findall(r"\d+",s)])[-1] 9988 #利用非數字,正則拆分出數字,求最大值 >>> max([int(num) for num in re.split(r"\D+",s)]) 9988 #字符串中所有非數字替換成空白,然後拆分成數字列表 >>> max([int(num) for num in re.sub(r"\D+"," ",s).split()]) 9988 #普通方法 >>> for v in s: ... if not v.isdigit(): ... s = s.replace(v," ") ... >>> max([int(v) for v in s.split()]) 9988 11、匹配不包含連續字符串abc的單詞。s='abcddd qweabee ddabc abc cba’ s='abcddd qweabee ddabc abc cba’ >>> [m.group() for m in re.finditer(r"\b((?!abc)\w)+\b",s)] ['qweabee', 'cba'] 如果用findall需要在正則表達式外加一個外層分組,findall只返回分組的內容,如果有分組 >>> re.findall(r"\b((?!abc)\w)+\b",s) ['e', 'a'] >>> re.findall(r"(\b((?!abc)\w)+\b)",s) [('qweabee', 'e'), ('cba', 'a')] 應該是沒理解(?!abc)的意義,(?!abc)匹配的是一個位置,不佔用任何字符. (?!abc)的意義就是從當前匹配到的位置起,接下來不是一個字符"a"接着一個字符"b"接着一個字符"c".(?!abc)\w的意義是用(?!abc)來限定\w的匹配,從\w的位置起不能出現一個字符"a"接着一個字符"b"接着一個字符"c".((?!abc)\w)+就是多個被限定的\w組成的單詞,這個單詞中肯定不會出現"abc". 再舉個例子: (?!office)[a-z]+2000:不匹配"office2000",匹配"windows2000" (?!a11)a:匹配"a10a11a12"中的第一個和第三個"a" 12、統計文章的字母個數 >>> with open("d:\\a.txt") as file_obj: ... print(len(re.findall(r"[a-zA-Z]",file_obj.read()))) ... 1 13、統計文章數字個數 >>> with open("d:\\a.txt") as file_obj: ... print(len(re.findall(r"\d",file_obj.read()))) ... 1 14、統計文章中的單詞個數 >>> with open("d:\\a.txt") as file_obj: ... print(len(re.findall(r"\b[a-z]+\b",file_obj.read(),re.I))) ... 1 16、獲取某個網頁的所有鏈接 #coding=utf-8 import re import requests res = requests.get("https://www.sogou.com") print(res.text) links = re.findall(r'href="(.*?)"',res.text) print(links) print(len(links)) 17、 刪除文章中所有數字 >>> with open("d:\\a.txt","r+") as file_obj: ... new = re.sub(r"\d","",file_obj.read()) ... file_obj.seek(0,0) ... file_obj.write("") ... file_obj.seek(0,0) ... file_obj.write(new) ... 0 0 0 7 18、 刪除後統計一下刪除組數 >>> re.subn(r"\d+","","a123 b456 c789d")[1] 3 19、 匹配一個ip IP地址是一個32位的二進制數,通常被分割爲4個“8位二進制數”(也就是4個字節)。IP地址通常用“點分十進制”表示成(a.b.c.d)的形式,其中,a,b,c,d都是0~255之間的十進制整數。例:點分十進IP地址(100.4.5.6),實際上是32位二進制數(01100100.00000100.00000101.00000110) pattern = re.compile(r'^(([0-9]|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.){3}([0-9]|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])$') pattern = re.compile(r'^((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.){3}(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])$') >>> pattern.match("0.0.0.0") <_sre.SRE_Match object; span=(0, 7), match='0.0.0.0'> >>> pattern.match("1.20.245.255") <_sre.SRE_Match object; span=(0, 10), match='1.20.245.2'> 20、 統計開頭不是a的所有單詞 >>> re.findall(r"\b(?!a)[a-zA-Z]+\b","abc cdea kkk") ['cdea', 'kkk'] >>> with open("d:\\a.txt","r+") as file_obj: ... print(re.findall(r"\b[b-zA-Z][a-zA-Z]+\b",file_obj.read())) ... ['good', 'boy'] 21、 匹配1900年到2999年 >>> re.match(r"(19\d{2}|2\d{3})年","1900年") <_sre.SRE_Match object; span=(0, 5), match='1900年'>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章