Python3 CookBook | 字符串和文本

作者: yongxinz | 来源:发表于2017-11-30 20:35 被阅读8次

    文章首发于知乎专栏,欢迎关注。
    https://zhuanlan.zhihu.com/pythoncookbook

    以下测试代码全部基于 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() 函数还有很多功能,比如打印的时候就常用它来格式化,有兴趣可以进行更多了解。

    未完待续。。。

    相关文章

      网友评论

        本文标题:Python3 CookBook | 字符串和文本

        本文链接:https://www.haomeiwen.com/subject/rzsbbxtx.html