使用界定符分割字符串
前言
需求是將字符串分割成多段,但是分隔符(周圍的空格)并不固定。
re.split()
普通 string 對象的 split() 方法能夠用于字符串分割,但前提是需求相對簡單的情況下,因?yàn)?string 對象的 split() 方法并不允許有多個(gè)分隔符或者分隔符周圍有不確定的空格。當(dāng)需要更加靈活地切割字符的時(shí)候,建議使用 re.split() 方法。示例如下:
>>> line = 'asdf fjdk; afed, fjek,asdf, foo'
>>> import re
>>> re.split(r'[;,\s]\s*', line)
['asdf', 'fjdk', 'afed', 'fjek', 'asdf', 'foo']
re.split() 允許為分隔符指定多個(gè)正則模式,上面的示例中表示,分隔符可以是分號、逗號或者空格,并且后面緊跟任意空格。只要這個(gè)模式被找到,那么匹配的分隔符兩邊的實(shí)體都會(huì)別當(dāng)成是結(jié)果中的元素返回。返回結(jié)果類型是列表。
maxsplit 和 flags 參數(shù)
這里延伸講下 re.split() 函數(shù)的參數(shù),該函數(shù)的完整表達(dá)形式如下:
re.split(pattern, string, maxsplit=0, flags=0)
-
pattern就是分割模式; -
string就是代表待分割的字符串; -
maxsplit默認(rèn)為 0,但如果這個(gè)參數(shù)非零,函數(shù)最多進(jìn)行maxsplit次分割,剩下的字符全部返回到列表的最后一個(gè)元素中; -
flags參數(shù)為可選標(biāo)記參數(shù),例如re.M,re.I等。
實(shí)例代碼演示 maxsplit 參數(shù)的效果
>>> re.split(r'\W+', 'Words, words, words.')
['Words', 'words', 'words', '']
>>> re.split(r'\W+', 'Words, words, words.', 1)
['Words', 'words, words.']
在第二段代碼中,函數(shù)只分割了一次,剩余元素都在列表中的最后一個(gè)元素中。
下面這段代碼是 flags 這個(gè)參數(shù)的一個(gè)應(yīng)用:
>>> re.split('[a-f]+', '0a3B9', flags=re.IGNORECASE)
['0', '3', '9']
>>> re.split('[a-f]+', '0a3B9', flags=re.I)
['0', '3', '9']
這里指定的標(biāo)記參數(shù)是 re.I 跟 re.IGNORECASE,但是兩者的效果等同,這兩者的作用是用于在匹配時(shí)忽略大小寫。
捕獲分組
使用 re.split() 函數(shù)的時(shí)候,還需要注意正則表達(dá)式是否包含一個(gè)括號的捕獲分組,如果在 pattern 中捕獲到括號,那么所有被匹配的文本,都會(huì)被當(dāng)成一部分返回在列表里。示例如下:
>>> re.split(r'\W+', 'Words, words, words.')
['Words', 'words', 'words', '']
>>> re.split(r'(\W+)', 'Words, words, words.')
['Words', ', ', 'words', ', ', 'words', '.', '']
>>> re.split(r'(\W+)', '...words, words...')
['', '...', 'words', ', ', 'words', '...', '']
\W 用于匹配特殊字符,在例子第二段代碼中,被匹配的字符,也作為一部分內(nèi)容返回在列表中。第三段代碼,表示的是,分割模式有捕獲分組,并且匹配到字符串的開始,那么結(jié)果將以一個(gè)空字符串開始,對于結(jié)尾也一樣。
如果不想保留分割字符到結(jié)果列表中,但仍然需要使用到括號來分組的情況下,可以用 (?:...) 來表達(dá)分組是非捕獲組,例如:
>>> re.split(r'(\W+)', 'Words, words, words.')
['Words', ', ', 'words', ', ', 'words', '.', '']
>>> re.split(r'(?:\W+)', 'Words, words, words.')
['Words', 'words', 'words', '']
注意事項(xiàng)
本篇文章運(yùn)行環(huán)境中,Python 的版本是 3.6 ,在未升級到 3.7 的版本中, split() 函數(shù)并不支持空匹配模式,例如,文檔中給出的注解:
Note: split() doesn’t currently split a string on an empty pattern match.
先給出示例代碼:
>>> re.split('x*', 'axbc')
...: FutureWarning: split() requires a non-empty pattern match.
return _compile(pattern, flags).split(string, maxsplit)
['a', 'bc']
正常情況下,x* 是能夠匹配 0 個(gè) x,無論是在 a 之前,b 和 c 之間還是 c 之后,然而這些都被忽略了。正確的結(jié)果應(yīng)該是形如 ['', 'a', 'b', 'c', ''],但這是一個(gè)向后不兼容的更改,所以會(huì)有 FutureWarning 警告拋出。
在 Python 3.6 中,空匹配模式還不被允許,強(qiáng)行使用的話,會(huì)拋出 ValueError 異常。例如:
>>> re.split("^$", 'foo\n\nbar\n', flags=re.M)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
...
ValueError: split() requires a non-empty pattern match.
但這部分內(nèi)容,已經(jīng)在 3.7 中做出了改動(dòng)。在 3.8 版本中的文檔中,有部分小注:
Changed in version 3.7: Added support of splitting on a pattern that could match an empty string.
這部分內(nèi)容表明,在 3.7版后 re.split() 已經(jīng)開始支持空匹配模式。
所以,如果使用 re.split() 空匹配模式的時(shí)候,效果未達(dá)預(yù)期,可以考慮是否是 Python 版本的原因。
以上就是本篇的主要內(nèi)容