文章首發於知乎專欄,歡迎關注。
zhuanlan.zhihu.com/pythoncookb…
以下測試程式碼全部基於 Python3。
字串操作在程式中的出現頻率相當高,包括分割,替換,拼接等等,這篇文章介紹五個最常遇到的問題,希望給你帶來一些思考。
1、使用多個界定符分割字串
分割字串屬於字串最基本的操作了,直接用 split() 即可。
In [88]: a = 'a,b,c,c'
In [89]: a.split(',')
Out[89]: ['a', 'b', 'c', 'c']複製程式碼
如果一個字串包含多個不同的分隔符呢?當然可以用 split() 進行多次分割,但這顯然比較麻煩,這時候用 re.split() 是更好的解決辦法。
In [90]: a = 'a,b c:d,e'
In [91]: import re
In [92]: re.split(r'[,| |:]', a)
Out[92]: ['a', 'b', 'c', 'd', 'e']複製程式碼
re.split() 函式的第一個引數可以根據你的需要,寫出符合要求的正規表示式。
2、字串開頭或結尾匹配
解決這個問題可以有很多種方法。
第一可以使用切片操作,擷取出字串和要求字串進行比較;第二可以使用 re.march() 函式,通過寫正規表示式,檢查匹配結果來達到比較目的。
這裡介紹兩個更簡單的函式 startswith() 和 endswith()。
In [93]: a = 'hello.py'
In [94]: a.endswith('.py')
Out[94]: True
In [95]: a.startswith('h')
Out[95]: True複製程式碼
需要注意的是,如果要一次比較多個字串,所傳入的引數必須是元組,否則會報錯。
In [96]: names = ['a.txt', 'b.py', 'c', 'd.py']
In [97]: [name for name in names if name.endswith('.py')]
Out[97]: ['b.py', 'd.py']
In [98]: [name for name in names if name.endswith('.py', '.txt')]
-----------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-98-900fc5940b5c> in <module>()
> 1 [name for name in names if name.endswith('.py', '.txt')]
<ipython-input-98-900fc5940b5c> in <listcomp>(.0)
> 1 [name for name in names if name.endswith('.py', '.txt')]
TypeError: slice indices must be integers or None or have an __index__ method
In [99]: [name for name in names if name.endswith(('.py', '.txt'))]
Out[99]: ['a.txt', 'b.py', 'd.py']複製程式碼
再來看另一種情況,我們用 Linux 系統 shell 命令時,很喜歡用萬用字元,比如 ls *.py 來檢視資料夾下所有 Python 檔案。
在程式中也有兩個函式,fnmatch() 和 fnmatchcase() 來支援這種萬用字元的操作方式。
In [100]: from fnmatch import fnmatch, fnmatchcase
In [101]: fnmatch('a.py', '*.py')
Out[101]: True複製程式碼
由於不同的作業系統,對於模式大小寫匹配規則是不一樣的,所以 fnmatchcase() 函式的作用就是完全按照模式大小寫來匹配。
3、字串搜尋和替換
對於簡單的模式,直接使用 replace() 函式即可。
In [102]: a = 'hello world'
In [103]: a.replace('hello', 'go')
Out[103]: 'go world'複製程式碼
如果是複雜的模式,可以使用 re.sub() 函式。比如你想把 ’11/30/2017’ 轉換成 ’2017-11-30‘。
In [104]: a = 'time is 11/30/2017'
In [106]: re.sub(r'(\d+)/(\d+)/(\d+)', r'\3-\1-\2', a)
Out[106]: 'time is 2017-11-30'複製程式碼
sub() 函式第一個參數列示原字串匹配模式,第二個引數是希望轉換成的模式,反斜槓 3 為前面獲取的組號。
其實這種解決方法歸根結底還是考驗對正規表示式理解程度,如果對正規表示式很熟悉的話,解決這類問題會很輕鬆。
我剛開始工作時用的語言是 Perl,這個語言對文字處理相當強悍,用的最多的就是正規表示式,寫起來也很方便,當時寫過很多很複雜的正則。後來開始寫 Python 之後,感覺寫正則好麻煩,很不習慣。
4、最短匹配和多行匹配模式
這兩個操作所要注意的就兩個方面。
第一,當使用 . 進行匹配時,所採用的模式為貪婪匹配,如果想要結果為最短匹配,需要寫成非貪婪匹配:.?。
第二,點號是不能匹配換行符的,所以在進行多行匹配時,要寫成:[.|\n]。
5、字串格式換
首先說說字串拼接,如果簡單拼接兩個字串,加號便可以輕鬆搞定。
In [110]: a = 'hello'
In [111]: b = 'world'
In [112]: a + ' ' + b
Out[112]: 'hello world'複製程式碼
如果拼接一個列表中的字串呢?可以用 join() 函式。
In [113]: a = ['I', 'have', 'a', 'dream']
In [114]: ' '.join(a)
Out[114]: 'I have a dream'複製程式碼
再來看看這類替換操作:
In [115]: a = '{name} is {age}'
In [116]: a.format(name='Tom', age=18)
Out[116]: 'Tom is 18'複製程式碼
其實 format() 函式還有很多功能,比如列印的時候就常用它來格式化,有興趣可以進行更多瞭解。
未完待續。。。