聊一聊'駝峰'和'下劃線'——Python re.sub函數(shù)詳細(xì)用法實(shí)例講解

日常寫代碼時(shí)候會(huì)遇到一些字符串替換的操作,比如把一大堆"駝峰"形式的字符串批量轉(zhuǎn)換成下劃線形式。"駝峰"形式的變量命名風(fēng)格在Java中很常見,而下劃線形式的變量命名風(fēng)格在C、Python等語言的代碼中更常見一些,兩者沒有嚴(yán)格的好壞區(qū)分。本文就用"駝峰"和"下劃線"相互轉(zhuǎn)換的實(shí)例,講解一下Python的re模塊sub函數(shù)的強(qiáng)大功能。

什么是"駝峰"和"下劃線"風(fēng)格的字符串

變量名、函數(shù)名等標(biāo)識(shí)符的多個(gè)單詞之間用下劃線隔開,這樣的字符串就是下劃線風(fēng)格的字符串,比如:

person_info
ipv6_address
book_id
get_tomorrow_weather()

而駝峰風(fēng)格的字符串就是不同單詞之間用大寫字母進(jìn)行分隔,比如:

personInfo
ipv6Address
bookId
getTomorrowWeather()

re.sub函數(shù)

re.sub函數(shù)是Python內(nèi)置的re模塊的一個(gè)字符串替換函數(shù),支持正則替換。函數(shù)文檔如下:

help(re.sub)
Help on function sub in module re:
sub(pattern, repl, string, count=0, flags=0)
    Return the string obtained by replacing the leftmost
    non-overlapping occurrences of the pattern in string by the
    replacement repl.  repl can be either a string or a callable;
    if a string, backslash escapes in it are processed.  If it is
    a callable, it's passed the match object and must return
    a replacement string to be used.

re.sub函數(shù)的函數(shù)原型為:sub(pattern, repl, string, count=0, flags=0)

下面簡(jiǎn)單介紹一下每個(gè)參數(shù)的含義:

  • pattern:是一個(gè)正則表達(dá)式,匹配要替換的子串。

  • repl:可以是一個(gè)字符串,支持對(duì)pattern中分組的后向引用。注意到文檔的最后一句話:

If it is a callable, it's passed the match object and must return a replacement string to be used.

可見,repl也可以是一個(gè)callable對(duì)象(函數(shù)),這個(gè)函數(shù)的入?yún)閜attern正則匹配到的對(duì)象,返回值為一個(gè)字符串,表示要替換成的字符串。

注:正則的分組及后向引用詳見:python正則表達(dá)式系列(4)——分組和后向引用

  • string:要進(jìn)行替換操作的字符串。

  • count:要替換掉多少個(gè)子串(按從左到右的順序),默認(rèn)值為0,表示替換能被pattern匹配到的所有子串。

  • flags:正則內(nèi)置屬性,默認(rèn)值為0,表示不使用任何內(nèi)置屬性。

注:正則內(nèi)置屬性的用法詳見:python正則表達(dá)式系列(3)——正則內(nèi)置屬性

"駝峰"和"下劃線"字符串之間的相互轉(zhuǎn)換

通過對(duì)re.sub函數(shù)的深入了解,現(xiàn)在應(yīng)該可以輕松寫出"駝峰"和"下劃線"字符串相互轉(zhuǎn)換的代碼了。直接上代碼:

# coding:utf-8
import re

def hump2underline(hunp_str):
    '''
    駝峰形式字符串轉(zhuǎn)成下劃線形式
    :param hunp_str: 駝峰形式字符串
    :return: 字母全小寫的下劃線形式字符串
    '''
    # 匹配正則,匹配小寫字母和大寫字母的分界位置
    p = re.compile(r'([a-z]|\d)([A-Z])')
    # 這里第二個(gè)參數(shù)使用了正則分組的后向引用
    sub = re.sub(p, r'\1_\2', hunp_str).lower()
    return sub

def underline2hump(underline_str):
    '''
    下劃線形式字符串轉(zhuǎn)成駝峰形式
    :param underline_str: 下劃線形式字符串
    :return: 駝峰形式字符串
    '''
    # 這里re.sub()函數(shù)第二個(gè)替換參數(shù)用到了一個(gè)匿名回調(diào)函數(shù),回調(diào)函數(shù)的參數(shù)x為一個(gè)匹配對(duì)象,返回值為一個(gè)處理后的字符串
    sub = re.sub(r'(_\w)',lambda x:x.group(1)[1].upper(),underline_str)
    return sub

代碼中已經(jīng)有詳細(xì)的注釋,還是比較好理解的。下面對(duì)這兩個(gè)函數(shù)進(jìn)行測(cè)試:

def test_hump2underline():
    # 供測(cè)試用的一些駝峰形式的字符串
    attr1 = 'PersonNamePattern'
    attr2 = 'IPv6Address'
    attr3 = 'personDetailInfo'
    attr4 = 'CCTV'
    attr5 = 'CCTVAddress'
    attr6 = 'name'
    attrs = [attr1,attr2,attr3,attr4,attr5,attr6]

    # 遍歷attrs進(jìn)行匹配和轉(zhuǎn)換,把駝峰形式的字符串轉(zhuǎn)成下劃線形式
    for attr in attrs:
        sub = hump2underline(attr)
        print sub

    # 輸出:
    '''
    person_name_pattern
    ipv6_address
    person_detail_info
    cctv
    cctvaddress
    name
    '''

def test_underline2hump():
    attr1 = 'person_name_pattern'
    attr2 = 'ipv6_address'
    attr3 = 'person_detail_info'
    attr4 = 'cctv'
    attr5 = 'cctvaddress'
    attr6 = 'name'
    attrs = [attr1, attr2, attr3, attr4, attr5, attr6]

    for attr in attrs:
        sub = underline2hump(attr)
        print sub

    # 輸出:
    '''
    personNamePattern
    ipv6Address
    personDetailInfo
    cctv
    cctvaddress
    name
    '''

JSON字符串字段名的"駝峰"轉(zhuǎn)"下劃線"

JSON是一種非常通用、輕量型的數(shù)據(jù)交換格式,與Python中的字典、Java中的Map具有相同的結(jié)構(gòu)。JSON中的字段名一般需要寫成下劃線的形式,但是有時(shí)候也會(huì)遇到字段名是"駝峰"形式的JSON文本,那么如何把一個(gè)JSON字符串中的所有字段名都從駝峰形式替換成下劃線形式呢?

因?yàn)榭紤]到j(luò)son可能具有多層嵌套的復(fù)雜結(jié)構(gòu),所以下面直接采用正則文本替換的方式進(jìn)行處理,而不是采用把JSON字符串轉(zhuǎn)成字典再進(jìn)行處理。

上代碼:

def json_hump2underline(hump_json_str):
    '''
    把一個(gè)json字符串中的所有字段名都從駝峰形式替換成下劃線形式。
    注意點(diǎn):因?yàn)榭紤]到j(luò)son可能具有多層嵌套的復(fù)雜結(jié)構(gòu),所以這里直接采用正則文本替換的方式進(jìn)行處理,而不是采用把json轉(zhuǎn)成字典再進(jìn)行處理的方式
    :param hump_json_str: 字段名為駝峰形式的json字符串
    :return: 字段名為下劃線形式的json字符串
    '''
    # 從json字符串中匹配字段名的正則
    # 注:這里的字段名只考慮由英文字母、數(shù)字、下劃線組成
    attr_ptn = re.compile(r'"\s*(\w+)\s*"\s*:')

    # 使用hump2underline函數(shù)作為re.sub函數(shù)第二個(gè)參數(shù)的回調(diào)函數(shù)
    sub = re.sub(attr_ptn,lambda x : '"' + hump2underline(x.group(1)) + '" :',hump_json_str)
    return sub

對(duì)上面這個(gè)函數(shù)進(jìn)行測(cè)試:

def test_json_hump2underline():
    # 待測(cè)試json字符串
    json_str = '''
    {
        "englishName":"Tom",
        "age":18,
        "detailInfoTable": {
            "address":"USA",
            "sportsHobby": ["Basketball","Football","Swimming"],
            "contactList":{
                "tel" : "1234567",
                "emailAddress":"tom@test.com"
            }
        },
        "gender":"male"
    }
    '''
    print json_hump2underline(json_str)

    # 輸出:
    '''
    {
        "english_name" :"Tom",
        "age" :18,
        "detail_info_table" : {
            "address" :"USA",
            "sports_hobby" : ["Basketball","Football","Swimming"],
            "contact_list" :{
                "tel" : "1234567",
                "email_address" :"tom@test.com"
            }
        },
        "gender" :"male"
    }
    '''

總結(jié)

經(jīng)過以上實(shí)例可以看出,re.sub函數(shù)因?yàn)橹С至苏齽t替換及回調(diào)函數(shù)替換,在處理復(fù)雜文本替換需求時(shí)具有強(qiáng)大的優(yōu)勢(shì),再一次展現(xiàn)了Python在文本處理領(lǐng)域功能強(qiáng)大又簡(jiǎn)單、易用的特點(diǎn)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • re模塊手冊(cè) 本模塊提供了和Perl里的正則表達(dá)式類似的功能,不關(guān)是正則表達(dá)式本身還是被搜索的字符串,都可以...
    喜歡吃栗子閱讀 4,197評(píng)論 0 13
  • http://python.jobbole.com/85231/ 關(guān)于專業(yè)技能寫完項(xiàng)目接著寫寫一名3年工作經(jīng)驗(yàn)的J...
    燕京博士閱讀 7,794評(píng)論 1 118
  • 【背景】Python中的正則表達(dá)式方面的功能,很強(qiáng)大。其中就包括re.sub,實(shí)現(xiàn)正則的替換。功能很強(qiáng)大,所以導(dǎo)致...
    NataliaTsunako閱讀 10,194評(píng)論 0 6
  • 概述 正則表達(dá)式是一個(gè)特殊的字符序列,它能幫助你方便的檢查一個(gè)字符串是否與某種模式匹配。 Python 自1....
    MiracleJQ閱讀 432評(píng)論 0 0
  • 太多場(chǎng)景需要做選擇,選擇有利的、簡(jiǎn)單的、快速的、自己擅長(zhǎng)的是人之常情。 所以, 罵人或者鼓勵(lì)...
    留下思考的痕跡閱讀 218評(píng)論 0 0

友情鏈接更多精彩內(nèi)容