文章首发于知乎专栏,欢迎关注。
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() 函数还有不少功能,好比打印的时候就经常使用它来格式化,有兴趣能够进行更多了解。
未完待续。。。