$聊一聊"駝峰"和"下划線"——Python re.sub函數詳細用法實例講解


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

什么是"駝峰"和"下划線"風格的字符串

變量名、函數名等標識符的多個單詞之間用下划線隔開,這樣的字符串就是下划線風格的字符串,比如:

person_info
ipv6_address
book_id
get_tomorrow_weather()

而駝峰風格的字符串就是不同單詞之間用大寫字母進行分隔,比如:

personInfo
ipv6Address
bookId
getTomorrowWeather()

re.sub函數

re.sub函數是Python內置的re模塊的一個字符串替換函數,支持正則替換。函數文檔如下:

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函數的函數原型為:sub(pattern, repl, string, count=0, flags=0)

下面簡單介紹一下每個參數的含義:

  • pattern:是一個正則表達式,匹配要替換的子串。

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

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

可見,repl也可以是一個callable對象(函數),這個函數的入參為pattern正則匹配到的對象,返回值為一個字符串,表示要替換成的字符串。

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

  • string:要進行替換操作的字符串。

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

  • flags:正則內置屬性,默認值為0,表示不使用任何內置屬性。

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

"駝峰"和"下划線"字符串之間的相互轉換

通過對re.sub函數的深入了解,現在應該可以輕松寫出"駝峰"和"下划線"字符串相互轉換的代碼了。直接上代碼:

# coding:utf-8
import re

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

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

代碼中已經有詳細的注釋,還是比較好理解的。下面對這兩個函數進行測試:

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

    # 遍歷attrs進行匹配和轉換,把駝峰形式的字符串轉成下划線形式
    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字符串字段名的"駝峰"轉"下划線"

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

因為考慮到json可能具有多層嵌套的復雜結構,所以下面直接采用正則文本替換的方式進行處理,而不是采用把JSON字符串轉成字典再進行處理。

上代碼:

def json_hump2underline(hump_json_str):
    '''
    把一個json字符串中的所有字段名都從駝峰形式替換成下划線形式。
    注意點:因為考慮到json可能具有多層嵌套的復雜結構,所以這里直接采用正則文本替換的方式進行處理,而不是采用把json轉成字典再進行處理的方式
    :param hump_json_str: 字段名為駝峰形式的json字符串
    :return: 字段名為下划線形式的json字符串
    '''
    # 從json字符串中匹配字段名的正則
    # 注:這里的字段名只考慮由英文字母、數字、下划線組成
    attr_ptn = re.compile(r'"\s*(\w+)\s*"\s*:')

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

對上面這個函數進行測試:

def test_json_hump2underline():
    # 待測試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"
    }
    '''

總結

經過以上實例可以看出,re.sub函數因為支持了正則替換及回調函數替換,在處理復雜文本替換需求時具有強大的優勢,再一次展現了Python在文本處理領域功能強大又簡單、易用的特點。


免責聲明!

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



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