Python3 CookBook | 字符串和文本

文章首發於知乎專欄,歡迎關注。
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() 函數還有不少功能,好比打印的時候就經常使用它來格式化,有興趣能夠進行更多瞭解。

未完待續。。。

相關文章
相關標籤/搜索