文章首發於知乎專欄,歡迎關注。
zhuanlan.zhihu.com/pythoncookb…python
如下測試代碼所有基於 Python3。正則表達式
字符串操做在程序中的出現頻率至關高,包括分割,替換,拼接等等,這篇文章介紹五個最常遇到的問題,但願給你帶來一些思考。shell
分割字符串屬於字符串最基本的操做了,直接用 split() 便可。bash
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() 函數的第一個參數能夠根據你的須要,寫出符合要求的正則表達式。測試
解決這個問題能夠有不少種方法。ui
第一可使用切片操做,截取出字符串和要求字符串進行比較;第二可使用 re.march() 函數,經過寫正則表達式,檢查匹配結果來達到比較目的。spa
這裏介紹兩個更簡單的函數 startswith() 和 endswith()。操作系統
In [93]: a = 'hello.py'
In [94]: a.endswith('.py')
Out[94]: True
In [95]: a.startswith('h')
Out[95]: True複製代碼
須要注意的是,若是要一次比較多個字符串,所傳入的參數必須是元組,不然會報錯。code
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() 函數的做用就是徹底按照模式大小寫來匹配。
對於簡單的模式,直接使用 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 以後,感受寫正則好麻煩,很不習慣。
這兩個操做所要注意的就兩個方面。
第一,當使用 . 進行匹配時,所採用的模式爲貪婪匹配,若是想要結果爲最短匹配,須要寫成非貪婪匹配:.?。
第二,點號是不能匹配換行符的,因此在進行多行匹配時,要寫成:[.|\n]。
首先說說字符串拼接,若是簡單拼接兩個字符串,加號即可以輕鬆搞定。
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() 函數還有不少功能,好比打印的時候就經常使用它來格式化,有興趣能夠進行更多瞭解。
未完待續。。。