最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python如何使用組合方式構(gòu)建復(fù)雜正則

 更新時間:2024年12月02日 15:31:28   作者:韋易笑  
在Python中正則寫復(fù)雜了很麻煩,難寫難調(diào)試,其實(shí)只需要兩個函數(shù),就能用簡單正則組合構(gòu)建復(fù)雜正則,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

正則寫復(fù)雜了很麻煩,難寫難調(diào)試,只需要兩個函數(shù),就能用簡單正則組合構(gòu)建復(fù)雜正則:

比如輸入一個字符串規(guī)則,可以使用 {name} 引用前面定義的規(guī)則:

# rules definition
rules = r'''
    protocol = http|https
    login_name = [^:@\r\n\t ]+
    login_pass = [^@\r\n\t ]+
    login = {login_name}(:{login_pass})?
    host = [^:/@\r\n\t ]+
    port = \d+
    optional_port = (?:[:]{port})?
    path = /[^\r\n\t ]*
    url = {protocol}://({login}[@])?{host}{optional_port}{path}?
'''

然后調(diào)用 regex_build 函數(shù),將上面的規(guī)則轉(zhuǎn)換成一個字典并輸出:

# expand patterns in a dictionary
m = regex_build(rules, capture = True)

# list generated patterns
for k, v in m.items(): 
    print(k, '=', v)

結(jié)果:

protocol = (?P<protocol>http|https)
login_name = (?P<login_name>[^:@\r\n\t ]+)
login_pass = (?P<login_pass>[^@\r\n\t ]+)
login = (?P<login>(?P<login_name>[^:@\r\n\t ]+)(:(?P<login_pass>[^@\r\n\t ]+))?)
host = (?P<host>[^:/@\r\n\t ]+)
port = (?P<port>\d+)
optional_port = (?P<optional_port>(?:[:](?P<port>\d+))?)
path = (?P<path>/[^\r\n\t ]*)
url = (?P<url>(?P<protocol>http|https)://((?P<login>(?P<login_name>[^:@\r\n\t ]+)(:(?P<login_pass>[^@\r\n\t ]+))?)[@])?(?P<host>[^:/@\r\n\t ]+)(?P<optional_port>(?:[:](?P<port>\d+))?)(?P<path>/[^\r\n\t ]*)?)

用手寫直接寫是很難寫出這么復(fù)雜的正則的,寫出來也很難調(diào)試,而組合方式構(gòu)建正則的話,可以將小的簡單正則提前測試好,要用的時候再組裝起來,就不容易出錯,上面就是組裝替換后的結(jié)果。

下面用里面的 url 這個規(guī)則來匹配一下:

# 使用規(guī)則 "url" 進(jìn)行匹配
pattern = m['url']
s = re.match(pattern, 'https://name:pass@www.baidu.com:8080/haha')

# 打印完整匹配結(jié)果
print('matched: "%s"'%s.group(0))
print()

# 打印分組匹配結(jié)果
for name in ('url', 'login_name', 'login_pass', 'host', 'port', 'path'):
    print('subgroup:', name, '=', s.group(name))

輸出:

match text with pattern "url"
matched: "https://name:pass@www.baidu.com:8080/haha"

subgroup: url = https://name:pass@www.baidu.com:8080/haha
subgroup: login_name = name
subgroup: login_pass = pass
subgroup: host = www.baidu.com
subgroup: port = 8080
subgroup: path = /haha

可以取完整結(jié)果,也可以按照規(guī)則名字,取得里面具體某個部件得匹配結(jié)果。

這下可以方便的寫復(fù)雜正則表達(dá)式了。

再 Python 的正則表達(dá)式里 {xxx} 是用來表示長度的,里面都是數(shù)字,如果里面是變量名的話不會和原有規(guī)則沖突,因此這個寫法是安全的。

實(shí)現(xiàn)代碼:

import re

# 將 pattern 里形如 {name} 的文本,用 macros 里的預(yù)定義規(guī)則替換
def regex_expand(macros, pattern, guarded = True):
    output = []
    pos = 0
    size = len(pattern)
    while pos < size:
        ch = pattern[pos]
        if ch == '\\':
            output.append(pattern[pos:pos + 2])
            pos += 2
            continue
        elif ch != '{':
            output.append(ch)
            pos += 1
            continue
        p2 = pattern.find('}', pos)
        if p2 < 0:
            output.append(ch)
            pos += 1
            continue
        p3 = p2 + 1
        name = pattern[pos + 1:p2].strip('\r\n\t ')
        if name == '':
            output.append(pattern[pos:p3])
            pos = p3
            continue
        elif name[0].isdigit():
            output.append(pattern[pos:p3])
            pos = p3
            continue
        elif ('<' in name) or ('>' in name):
            raise ValueError('invalid pattern name "%s"'%name)
        if name not in macros:
            raise ValueError('{%s} is undefined'%name)
        if guarded:
            output.append('(?:' + macros[name] + ')')
        else:
            output.append(macros[name])
        pos = p3
    return ''.join(output)

# 給定規(guī)則文本,構(gòu)建規(guī)則字典
def regex_build(code, macros = None, capture = True):
    defined = {}
    if macros is not None:
        for k, v in macros.items():
            defined[k] = v
    line_num = 0
    for line in code.split('\n'):
        line_num += 1
        line = line.strip('\r\n\t ')
        if (not line) or line.startswith('#'):
            continue
        pos = line.find('=')
        if pos < 0:
            raise ValueError('%d: not a valid rule'%line_num)
        head = line[:pos].strip('\r\n\t ')
        body = line[pos + 1:].strip('\r\n\t ')
        if (not head):
            raise ValueError('%d: empty rule name'%line_num)
        elif head[0].isdigit():
            raise ValueError('%d: invalid rule name "%s"'%(line_num, head))
        elif ('<' in head) or ('>' in head):
            raise ValueError('%d: invalid rule name "%s"'%(line_num, head))
        try:
            pattern = regex_expand(defined, body, guarded = not capture)
        except ValueError as e:
            raise ValueError('%d: %s'%(line_num, str(e)))
        try:
            re.compile(pattern)
        except re.error:
            raise ValueError('%d: invalid pattern "%s"'%(line_num, pattern))
        if not capture:
            defined[head] = pattern
        else:
            defined[head] = '(?P<%s>%s)'%(head, pattern)
    return defined

# 定義一套組合規(guī)則
rules = r'''
    protocol = http|https
    login_name = [^:@\r\n\t ]+
    login_pass = [^@\r\n\t ]+
    login = {login_name}(:{login_pass})?
    host = [^:/@\r\n\t ]+
    port = \d+
    optional_port = (?:[:]{port})?
    path = /[^\r\n\t ]*
    url = {protocol}://({login}[@])?{host}{optional_port}{path}?
'''

# 將上面的規(guī)則展開成字典
m = regex_build(rules, capture = True)

# 輸出字典內(nèi)容
for k, v in m.items(): 
    print(k, '=', v)

print()

# 用最終規(guī)則 "url" 匹配文本
pattern = m['url']
s = re.match(pattern, 'https://name:pass@www.baidu.com:8080/haha')

# 打印完整匹配
print('matched: "%s"'%s.group(0))
print()

# 按名字打印分組匹配
for name in ('url', 'login_name', 'login_pass', 'host', 'port', 'path'):
    print('subgroup:', name, '=', s.group(name))

完事,主要邏輯 84 行代碼。

到此這篇關(guān)于Python如何使用組合方式構(gòu)建復(fù)雜正則的文章就介紹到這了,更多相關(guān)Python構(gòu)建復(fù)雜正則內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 簡單了解python 郵件模塊的使用方法

    簡單了解python 郵件模塊的使用方法

    這篇文章主要介紹了簡單了解python 郵件模塊的使用方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-07-07
  • python爬取2021貓眼票房字體加密實(shí)例

    python爬取2021貓眼票房字體加密實(shí)例

    在本篇文章里小編給大家整理的是一篇關(guān)于python爬取2021貓眼票房字體加密實(shí)例內(nèi)容,有興趣的朋友們可以學(xué)習(xí)下。
    2021-02-02
  • OPENCV去除小連通區(qū)域,去除孔洞的實(shí)例講解

    OPENCV去除小連通區(qū)域,去除孔洞的實(shí)例講解

    今天小編就為大家分享一篇OPENCV去除小連通區(qū)域,去除孔洞的實(shí)例講解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-06-06
  • pandas中Series和DataFrame的rank方法解析

    pandas中Series和DataFrame的rank方法解析

    pandas中的rank方法是用于數(shù)據(jù)排名的重要工具,它不返回排序后的數(shù)據(jù),而是數(shù)據(jù)的排名。rank方法可以處理相同數(shù)據(jù)的排名,通過平均排名方式解決排名沖突,并支持自定義排序規(guī)則及逆序排名。此外,DataFrame的rank方法允許在行或列上計算排名
    2024-09-09
  • python實(shí)現(xiàn)隨機(jī)調(diào)用一個瀏覽器打開網(wǎng)頁

    python實(shí)現(xiàn)隨機(jī)調(diào)用一個瀏覽器打開網(wǎng)頁

    下面小編就為大家分享一篇python實(shí)現(xiàn)隨機(jī)調(diào)用一個瀏覽器打開網(wǎng)頁,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-04-04
  • 最新python 字符串?dāng)?shù)組互轉(zhuǎn)問題

    最新python 字符串?dāng)?shù)組互轉(zhuǎn)問題

    這篇文章主要介紹了最新python 字符串?dāng)?shù)組互轉(zhuǎn)問題,主要介紹了字符串轉(zhuǎn)list數(shù)組問題和list數(shù)組轉(zhuǎn)字符串問題,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2023-02-02
  • pip指定python位置安裝軟件包的方法

    pip指定python位置安裝軟件包的方法

    今天小編就為大家分享一篇pip指定python位置安裝軟件包的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-07-07
  • 刪除目錄下相同文件的python代碼(逐級優(yōu)化)

    刪除目錄下相同文件的python代碼(逐級優(yōu)化)

    讓我們來分析一下這個問題:首先,文件個數(shù)非常多,手工查找是不現(xiàn)實(shí)的,再說,單憑我們?nèi)庋?,在幾千張圖片里面找到完全相同的難度也是很大的
    2012-05-05
  • Django的HttpRequest和HttpResponse對象詳解

    Django的HttpRequest和HttpResponse對象詳解

    這篇文章主要介紹了Django的HttpRequest和HttpResponse對象,分享了相關(guān)代碼示例,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下
    2018-01-01
  • 手把手帶你用python爬取小姐姐私房照

    手把手帶你用python爬取小姐姐私房照

    這篇文章主要介紹了用python如何爬取小姐姐私房照,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-08-08

最新評論

略阳县| 汽车| 谷城县| 开化县| 北海市| 临夏县| 洪洞县| 黄龙县| 汉阴县| 桓仁| 资阳市| 无棣县| 砀山县| 阿合奇县| 贵定县| 通城县| 绩溪县| 嘉定区| 长武县| 德化县| 乐昌市| 呼伦贝尔市| 凤山市| 柞水县| 定州市| 福鼎市| 延安市| 黄陵县| 神池县| 北宁市| 肥西县| 白朗县| 长沙市| 济南市| 银川市| 台安县| 车险| 庐江县| 双流县| 清远市| 连城县|