1.針對任意多的分隔符拆分字符串
問題:我們需要將字符串拆分為不同的字段,但是分隔符(以及分隔符之間的空格)在整個字符串中并不一致
解答:字符串對象的split()方法只能處理非常簡單的情況,而且不支持多個分隔符,對分隔符周圍可能存在的空格也無能為力。但是可以使用re.split()
>>>line = 'asdf fdjk; afed fjd,askjf, foo'
>>>import re
>>> re.split(r'[;,\s]\s*',line)
2.在字符串的開頭或者結尾處做文本匹配
問題:我們需要在字符串的開頭或者結尾處按照指定的文本模式做檢查,例如檢查文件的擴展名、url協議類型等;
解決方案:有一種簡單的方法來檢查字符串的開頭或者結尾:
startswith() 和 endswith()
如果是做列表的字符串檢查并篩選的話,可以配套列表推導式;
if any(name.endswith(('.c','.h')) for name in listdir(dirname)):
3.利用shell通配符做字符串匹配
4.文本模式的匹配和查找
如果想要匹配的只是簡單的文字,那么通常只需要用基本的字符串方法就可以了,比如:str.find(), str.endswith(),str.startswith()或類似的函數;
>>>text = 'year, but no,but yeah,but bo,but yeah'
>>>text.startswith('yeah') #True
>>>text.endswith('no') #False
>>>text.find('no') #10
對于更為復雜的匹配則需要用到正則表達式以及RE模塊:
>>>text1 = '11/27/2017'
>>>import re
>>> if re.match(r'\d+/\d+/\d+',text):
>>> print('yes')
match()方法總是嘗試在字符串的開頭找到匹配項,如果想針對真?zhèn)€文本搜索出所有的匹配項,那么應該使用findall()方法;
findall()方法搜索整個文本并找出所有的匹配項然后將他們以列表的形式返回,如果想以迭代的方式找出匹配項,可以使用finditer()方法;
>>>text = 'Today is 11/27/2017. pcCon starts 3/13/2015'
>>>datepat = re.compile(r'\d+/\d+/\d+')
>>>datepat.findall(text)
當定義正則表達式的時候,我們經常會將部分模式用括號包起來的方式引入捕獲組,
datapat = re.compile(r'(\d+)/(\d+)/(\d+)')
捕獲組通常能簡化后續(xù)對匹配結果的處理,因為每個組的內容都可以單獨提取出來;
5.查找和替換文本
問題:我們想對字符串的文本做查找和替換
解決方案:對于簡單的文本模式,使用str.replace()即可;
>>>text = 'Today is 11/27/2017. pcCon starts 3/13/2015'
>>>text.replace('yeah','yep')
針對更加復雜的模式,可以使用re模塊中的sub()函數方法。為了說明如何使用,假設我們想把日期格式從“11/27/2017”改寫為“2017-11-27”:
>>>text = 'Today is 11/27/2017. pcCon starts 3/13/2015'
>>>re.sub(r'(\d+)/(\d+)/(\d+)',r'\3-\1-\2',text)
sub()的第一個參數是要匹配的模式,第二個參數是要替換上的模式。類似“\3”這樣的反斜線加數字的符號代表著模式中捕獲組的數量;
如果打算用相同的模式執(zhí)行重復的替換,可以考慮先將模式編譯以獲取更好的性能;
>>>import re
>>>datepat = re.compile(r'(\d+)/(\d+)/(\d+)')
>>>datepat.sub(r'\3-\1-\2',text)
'Today is 2017-11-27.pcCon starts 2015-3-13'
除了得到替換后的文本外,如果還想知道一共完成了多少次替換,可以使用re.subn().
>>>newtext ,n = datepat.subn(r'\3-\1-\2',text)
>>>newtext
'Today is 2017-11-27.pcCon starts 2015-3-13'
>>>n
2
6.以不區(qū)分大小寫的方式對文本做查找和替換
問題:我們需要以不區(qū)分大小寫的方式在文本中進行查找,可能還需要做替換
解決方案:要進行不區(qū)分大小寫的文本操作,我們需要使用re模塊并且對各種操作都要加上re.IGNORECASE標記;
| 修飾符 | 描述 |
|---|---|
| re.I | 使匹配對大小寫不敏感 |
| re.L | 做本地化識別(locale-aware)匹配 |
| re.M | 多行匹配,影響 ^ 和 $ |
| re.S | 使 . 匹配包括換行在內的所有字符 |
| re.U | 根據Unicode字符集解析字符。這個標志影響 \w, \W, \b, \B. |
| re.X | 該標志通過給予你更靈活的格式以便你將正則表達式寫得更易于理解 |
7.定義實現最短匹配的正則表達式
問題:我們正在嘗試用正則表達式對文本模式做匹配,單識別出來的是最長的可能匹配,相反,我們想將其修改為找出最短的可能匹配;
解決方案:模式:r'(.)'嘗試去匹配將包含在引號中的文本,但是,操作符在正則表達式中時貪心策略,所以匹配過程是基于找出最長的可能匹配來進行的。要解決這個問題,只要在模式中的操作符后面加上?修飾符就可以了; ==> r'(.?)'
8.編寫多行模式的正則表達式
9.將Unicode文本統(tǒng)一為規(guī)范形式
10.用正則表達式處理Unicode字符;
11.從字符串中去掉不需要的字符
問題:我們想在字符串的開始,結尾或者中間去掉不需要的字符,比如說空格符;
解決方案:strip()方法可以用來充字符串開始或者結尾處去掉字符,lstrip()和rstrip()分別充左邊、右邊開始執(zhí)行去掉字符的操作。默認情況下這些方法去掉的是空格符,但也可以指定字符;
>>>str.strip() #默認情況下去掉空格符
>>>str.strip('/') #去掉指定的字符
上面的操作只能去掉字符串開始或者結尾處的字符,但是對于字符串中間的指定字符并不起作用;如果想要對里面的空格執(zhí)行某些操作,應該使用其他技巧,比如正則表達式或者replace()方法;
>>>s.replace(' ' ,'')
>>>re.sub('\s+','',s)
12.文本過濾和清理
13.對其文本字符串
問題:我們需要以某種對齊方式將文本做格式化處理
解決方案:對于基本的字符串對齊的要求,可以使用字符串的ljust(),rjust()和center()方法,
>>> text = 'Hello world'
>>> text.ljust(2)
'Hello world'
>>> text.ljust(20)
'Hello world '
>>> text.rjust(20)
' Hello world'
>>> text.center(20)
' Hello world '
>>> text.rjust(20,'=')
'=========Hello world'
>>> text.ljust(20,'=')
'Hello world========='
>>> text.center(20,'=')
'====Hello world====='
>>>
format()函數也可以用來輕松的完成對齊任務。需要做的就是合理的利用‘>’、‘<’或者‘^’字符串以及一個期望的寬度值
>>> format(text,'>20')
' Hello world'
>>> format(text,'<20')
'Hello world '
>>> format(text,'^20')
' Hello world
>>> format(text,'*^20')
'****Hello world*****'
>>> format(text,'*<20')
'Hello world*********'
14.字符串鏈接和合并
問題:我們想將很多小字符串合并成一個大的字符串;
解決方案:如果想要合并的字符串在一個序列或者可迭代對象中,那么將他們合并起來的最快方式是使用join()方法;
>>> parts = ['Is','Chicago','Not','Chicago?']
>>> ' '.join(parts)
'Is Chicago Not Chicago?'
對于簡單的幾個字符串的連接可以直接使用“+”操作符;
>>> a = 'Is Chicago'
>>> b = 'Not Chicago?'
>>> a + ' ' + b
'Is Chicago Not Chicago?'
針對更加負責的字符串格式操作,+操作符同樣可以作為format()的替代,
>>> print('{} {}'.format(a,b))
Is Chicago Not Chicago?
對于列表中的格式不統(tǒng)一的時候;我們需要處理后才能join()
>>> data = ['ACME',50,91.1]
>>> ','.join(data)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: sequence item 1: expected str instance, int found
>>> ','.join(str(d) for d in data)
'ACME,50,91.1'
15.給字符串中的變量名做插值處理
問題:想創(chuàng)建一個字符串,其中嵌入的變量名會以變量的字符串值形式替換掉;
解決方案:Python并不支持在字符串中對變量做簡單的值替換,但是,這個功能可以通過字符串的format()方法近似的模擬出來;
>>> s = '{name} has {n} messages.'
>>> s.format(name='overad',n=37)
'overad has 37 messages.'
兩一種方式:如果要替換的值確實能在變量中找到,則可以將format_map()和vars()聯合起來使用,示例如下:
>>> name = 'overad'
>>> n = 33
>>> s.format_map(vars())
'overad has 33 messages.'
上面的兩種方法都無法優(yōu)雅的處理缺少某個值的情況;避免出現這種情況的一種方法就是單獨定義一個帶有missing()方法的類,
>>> class safesub(dict):
... def __missing__(self,key):
... return '{' + key + '}'
...
>>> del n
>>> s.format_map(safesub(vars()))
'overad has {n} messages.'
如果發(fā)現自己在代碼中常常需要執(zhí)行這些步驟,則可以將替換變量的過程隱藏在一個小型的功能函數內;
>>> import sys
>>> def sub(text):
... return text.format_map(safesub(sys._getframe(1).f_locals))
...
>>> name = 'overad'
>>> n = 37
>>> print(sub('Hello {name}'))
Hello overad
>>> print(sub('You have {n} messages.'))
You have 37 messages.
>>> print('You favourite color is {color}')
You favourite color is {color}
16.以固定的列數重新格式化文本
問題:我們有一些很長的字符串,想將他們重新格式化,使得他們能按照用戶指定的列數來顯示;
解決方案:可以使用textwrap模塊來重新格式化文本的輸出;
>>>import textwrap
>>>print(textwrap.fill(s,70))
textwrap 模塊能夠以簡單直接的方式對文本格式做整理使其適合于答應--尤其是當希望輸出結果能很好地顯示在終端上時;關于終端的尺寸大小,可以通過os.get_terminal_size()來獲??;
>>> import os
>>> os.get_terminal_size()
os.terminal_size(columns=105, lines=28)