美文网首页
第二章:字符串和文本

第二章:字符串和文本

作者: overad | 来源:发表于2018-03-06 10:18 被阅读0次

    1.针对任意多的分隔符拆分字符串

    问题:我们需要将字符串拆分为不同的字段,但是分隔符(以及分隔符之间的空格)在整个字符串中并不一致

    解答:字符串对象的split()方法只能处理非常简单的情况,而且不支持多个分隔符,对分隔符周围可能存在的空格也无能为力。但是可以使用re.split()

    >>>line = 'asdf fdjk; afed fjd,askjf,      foo'
    >>>import re
    >>> re.split(r'[;,\s]\s*',line)
    

    2.在字符串的开头或者结尾处做文本匹配

    问题:我们需要在字符串的开头或者结尾处按照指定的文本模式做检查,例如检查文件的扩展名、url协议类型等;

    解决方案:有一种简单的方法来检查字符串的开头或者结尾:
    startswith() 和 endswith()
    如果是做列表的字符串检查并筛选的话,可以配套列表推导式;

    if any(name.endswith(('.c','.h')) for name in listdir(dirname)):

    3.利用shell通配符做字符串匹配

    4.文本模式的匹配和查找

    如果想要匹配的只是简单的文字,那么通常只需要用基本的字符串方法就可以了,比如:str.find(), str.endswith(),str.startswith()或类似的函数;

    >>>text = 'year, but no,but yeah,but bo,but yeah'
    >>>text.startswith('yeah')        #True
    >>>text.endswith('no')             #False
    >>>text.find('no')                       #10
    

    对于更为复杂的匹配则需要用到正则表达式以及RE模块:

    >>>text1 = '11/27/2017'
    >>>import re 
    >>> if re.match(r'\d+/\d+/\d+',text):
     >>>  print('yes')
    

    match()方法总是尝试在字符串的开头找到匹配项,如果想针对真个文本搜索出所有的匹配项,那么应该使用findall()方法;
    findall()方法搜索整个文本并找出所有的匹配项然后将他们以列表的形式返回,如果想以迭代的方式找出匹配项,可以使用finditer()方法;

    >>>text = 'Today is 11/27/2017. pcCon starts 3/13/2015'
    >>>datepat = re.compile(r'\d+/\d+/\d+')
    >>>datepat.findall(text)
    

    当定义正则表达式的时候,我们经常会将部分模式用括号包起来的方式引入捕获组,
    datapat = re.compile(r'(\d+)/(\d+)/(\d+)')

    捕获组通常能简化后续对匹配结果的处理,因为每个组的内容都可以单独提取出来;

    5.查找和替换文本

    问题:我们想对字符串的文本做查找和替换

    解决方案:对于简单的文本模式,使用str.replace()即可;

    >>>text = 'Today is 11/27/2017. pcCon starts 3/13/2015'
    >>>text.replace('yeah','yep')
    

    针对更加复杂的模式,可以使用re模块中的sub()函数方法。为了说明如何使用,假设我们想把日期格式从“11/27/2017”改写为“2017-11-27”:

    >>>text = 'Today is 11/27/2017. pcCon starts 3/13/2015'
    >>>re.sub(r'(\d+)/(\d+)/(\d+)',r'\3-\1-\2',text)
    

    sub()的第一个参数是要匹配的模式,第二个参数是要替换上的模式。类似“\3”这样的反斜线加数字的符号代表着模式中捕获组的数量;
    如果打算用相同的模式执行重复的替换,可以考虑先将模式编译以获取更好的性能;

    >>>import re
    >>>datepat = re.compile(r'(\d+)/(\d+)/(\d+)')
    >>>datepat.sub(r'\3-\1-\2',text)
    'Today is 2017-11-27.pcCon starts 2015-3-13'
    

    除了得到替换后的文本外,如果还想知道一共完成了多少次替换,可以使用re.subn().

    >>>newtext ,n = datepat.subn(r'\3-\1-\2',text)
    >>>newtext
    'Today is 2017-11-27.pcCon starts 2015-3-13'
    >>>n
    2
    

    6.以不区分大小写的方式对文本做查找和替换

    问题:我们需要以不区分大小写的方式在文本中进行查找,可能还需要做替换

    解决方案:要进行不区分大小写的文本操作,我们需要使用re模块并且对各种操作都要加上re.IGNORECASE标记;

    修饰符 描述
    re.I 使匹配对大小写不敏感
    re.L 做本地化识别(locale-aware)匹配
    re.M 多行匹配,影响 ^ 和 $
    re.S 使 . 匹配包括换行在内的所有字符
    re.U 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B.
    re.X 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解

    7.定义实现最短匹配的正则表达式

    问题:我们正在尝试用正则表达式对文本模式做匹配,单识别出来的是最长的可能匹配,相反,我们想将其修改为找出最短的可能匹配;

    解决方案:模式:r'(.)'尝试去匹配将包含在引号中的文本,但是,操作符在正则表达式中时贪心策略,所以匹配过程是基于找出最长的可能匹配来进行的。要解决这个问题,只要在模式中的操作符后面加上?修饰符就可以了; ==> r'(.?)'

    8.编写多行模式的正则表达式

    9.将Unicode文本统一为规范形式

    10.用正则表达式处理Unicode字符;

    11.从字符串中去掉不需要的字符

    问题:我们想在字符串的开始,结尾或者中间去掉不需要的字符,比如说空格符;

    解决方案:strip()方法可以用来充字符串开始或者结尾处去掉字符,lstrip()和rstrip()分别充左边、右边开始执行去掉字符的操作。默认情况下这些方法去掉的是空格符,但也可以指定字符;

    >>>str.strip()    #默认情况下去掉空格符
    >>>str.strip('/')  #去掉指定的字符
    

    上面的操作只能去掉字符串开始或者结尾处的字符,但是对于字符串中间的指定字符并不起作用;如果想要对里面的空格执行某些操作,应该使用其他技巧,比如正则表达式或者replace()方法;

    >>>s.replace(' ' ,'')
    >>>re.sub('\s+','',s)
    

    12.文本过滤和清理

    13.对其文本字符串

    问题:我们需要以某种对齐方式将文本做格式化处理

    解决方案:对于基本的字符串对齐的要求,可以使用字符串的ljust(),rjust()和center()方法,

    >>> text = 'Hello world'
    >>> text.ljust(2)
    'Hello world'
    >>> text.ljust(20)
    'Hello world         '
    >>> text.rjust(20)
    '         Hello world'
    >>> text.center(20)
    '    Hello world     '
    >>> text.rjust(20,'=')
    '=========Hello world'
    >>> text.ljust(20,'=')
    'Hello world========='
    >>> text.center(20,'=')
    '====Hello world====='
    >>>
    

    format()函数也可以用来轻松的完成对齐任务。需要做的就是合理的利用‘>’、‘<’或者‘^’字符串以及一个期望的宽度值

    >>> format(text,'>20')
    '         Hello world'
    >>> format(text,'<20')
    'Hello world         '
    >>> format(text,'^20')
    '    Hello world
    >>> format(text,'*^20')
    '****Hello world*****'
    >>> format(text,'*<20')
    'Hello world*********'
    

    14.字符串链接和合并

    问题:我们想将很多小字符串合并成一个大的字符串;

    解决方案:如果想要合并的字符串在一个序列或者可迭代对象中,那么将他们合并起来的最快方式是使用join()方法;

    >>> parts = ['Is','Chicago','Not','Chicago?']
    >>> ' '.join(parts)
    'Is Chicago Not Chicago?'
    

    对于简单的几个字符串的连接可以直接使用“+”操作符;

    >>> a = 'Is Chicago'
    >>> b = 'Not Chicago?'
    >>> a + ' ' + b
    'Is Chicago Not Chicago?'
    

    针对更加负责的字符串格式操作,+操作符同样可以作为format()的替代,

    >>> print('{} {}'.format(a,b))
    Is Chicago Not Chicago?
    

    对于列表中的格式不统一的时候;我们需要处理后才能join()

    >>> data = ['ACME',50,91.1]
    >>> ','.join(data)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: sequence item 1: expected str instance, int found
    >>> ','.join(str(d) for d in data)
    'ACME,50,91.1'
    

    15.给字符串中的变量名做插值处理

    问题:想创建一个字符串,其中嵌入的变量名会以变量的字符串值形式替换掉;

    解决方案:Python并不支持在字符串中对变量做简单的值替换,但是,这个功能可以通过字符串的format()方法近似的模拟出来;

    >>> s = '{name} has {n} messages.'
    >>> s.format(name='overad',n=37)
    'overad has 37 messages.'
    

    两一种方式:如果要替换的值确实能在变量中找到,则可以将format_map()和vars()联合起来使用,示例如下:

    >>> name = 'overad'
    >>> n = 33
    >>> s.format_map(vars())
    'overad has 33 messages.'
    

    上面的两种方法都无法优雅的处理缺少某个值的情况;避免出现这种情况的一种方法就是单独定义一个带有missing()方法的类,

    >>> class safesub(dict):
    ...     def __missing__(self,key):
    ...             return '{' + key + '}'
    ...
    >>> del n
    >>> s.format_map(safesub(vars()))
    'overad has {n} messages.'
    

    如果发现自己在代码中常常需要执行这些步骤,则可以将替换变量的过程隐藏在一个小型的功能函数内;

    >>> import sys
    >>> def sub(text):
    ...     return text.format_map(safesub(sys._getframe(1).f_locals))
    ...
    >>> name = 'overad'
    >>> n = 37
    >>> print(sub('Hello {name}'))
    Hello overad
    >>> print(sub('You have {n} messages.'))
    You have 37 messages.
    >>> print('You favourite color is {color}')
    You favourite color is {color}
    

    16.以固定的列数重新格式化文本

    问题:我们有一些很长的字符串,想将他们重新格式化,使得他们能按照用户指定的列数来显示;

    解决方案:可以使用textwrap模块来重新格式化文本的输出;

    >>>import textwrap
    >>>print(textwrap.fill(s,70))
    

    textwrap 模块能够以简单直接的方式对文本格式做整理使其适合于答应--尤其是当希望输出结果能很好地显示在终端上时;关于终端的尺寸大小,可以通过os.get_terminal_size()来获取;

    >>> import os
    >>> os.get_terminal_size()
    os.terminal_size(columns=105, lines=28)
    

    17.在文本中处理HTML和XML实体

    18.文本分词

    19.编写一个简单的递归下降解析器

    20.在字符串上执行文本操作

    相关文章

      网友评论

          本文标题:第二章:字符串和文本

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