平常寫代碼時候會遇到一些字符串替換的操做,好比把一大堆"駝峯"形式的字符串批量轉換成下劃線形式。"駝峯"形式的變量命名風格在Java中很常見,而下劃線形式的變量命名風格在C、Python等語言的代碼中更常見一些,二者沒有嚴格的好壞區分。本文就用"駝峯"和"下劃線"相互轉換的實例,講解一下Python的re模塊sub函數的強大功能。html
變量名、函數名等標識符的多個單詞之間用下劃線隔開,這樣的字符串就是下劃線風格的字符串,好比:python
person_info ipv6_address book_id get_tomorrow_weather()
而駝峯風格的字符串就是不一樣單詞之間用大寫字母進行分隔,好比:正則表達式
personInfo ipv6Address bookId getTomorrowWeather()
re.sub函數是Python內置的re模塊的一個字符串替換函數,支持正則替換。函數文檔以下:json
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)
app
下面簡單介紹一下每一個參數的含義:函數
pattern:是一個正則表達式,匹配要替換的子串。測試
repl:能夠是一個字符串,支持對pattern中分組的後向引用。注意到文檔的最後一句話:code
If it is a callable, it's passed the match object and must return a replacement string to be used.htm
可見,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是一種很是通用、輕量型的數據交換格式,與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在文本處理領域功能強大又簡單、易用的特色。