Python3 CookBook | 字串和文字

yongxinz發表於2017-12-01

文章首發於知乎專欄,歡迎關注。
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() 函式還有很多功能,比如列印的時候就常用它來格式化,有興趣可以進行更多瞭解。

未完待續。。。

相關文章