2007-06-19

 

Python Cookbook 1.15 控制和转换Tab字符

需求:

需要将字符串中指定数量的空格和Tab相互转换.

讨论:

空格和Tab的相互转换在文本处理中是很常见的需求,在Python中,可以方便的使用expandtabs方法来实现这个需求.因为字符串是不可以修改的,所以该方法返回了源字符串的一个副本.当然 ,我们可以将源字符串的名称绑定到修改后的字符串上.显然两个对象是不同的,如:

mystring = 'hello\tworld'
old = mystring
mystring = mystring.expandtabs()
print id(old)
print id(mystring)

>>> 30896000
30896048

这样并不改变源字符串所指向的对象,而是mystring指向了新构造的字符串.默认的情况下,expandtabs使用8个空格替换Tab,你可以传递希望的数字做为expandtabs的参数:

把空格转换为Tab是比较少见的需求,所以在Python中,并没有提供这样的方法.我们可以自己来写代码完成这个需求 ,在Python中,使用"分割/处理/合并"这样的流程处理和转换字符串是最有效的.

def unexpand(astring, tablen=8):
    import re
    # split into alternating space and non-space sequences
    pieces = re.split(r'( +)', astring.expandtabs(tablen))
    # keep track of the total length of the string so far
    lensofar = 0
    for i, piece in enumerate(pieces):
        thislen = len(piece)
        lensofar += thislen
        if piece.isspace( ):
            # change each space sequences into tabs+spaces
            numblanks = lensofar % tablen
            numtabs = (thislen-numblanks+tablen-1)/tablen
            pieces[i] = '\t'*numtabs + ' '*numblanks
    return ''.join(pieces)

这里写的方法只适用于当行字符串,如果多行字符串,请使用
' '.join([ unexpand(s) for s in astring.splitlines(True) ]).

上面的方法使用正则式来处理字符串,在很多语言中, 正则式都是处理字符串的利器.在上面的方法中,使用re的split方法来完成需求,它返回了一个序列,里面是用原先用空白字符分隔的字符串和空白字符.接下来,我们对每一个空白字符进行处理,尽可能多的把它们替换成Tab.

在编程中可能遇到另外的需求,比如处理行首的缩进.在Python中,需要检查源码中的缩进是否一致,是否有空格和Tab混用的情况,然后可以把它们统一换成空格.使用上面的方法会遇到一个问题,就是也会替换行中的Tab或空格,而这也许不是想要的结果,遇到这样的情况,我们需要修改一下正则式:

def expand_at_linestart(P, tablen=8):
    import re
    def exp(mo):
        return mo.group( ).expand(tablen)
    return ''.join([ re.sub(r'^\s+', exp, s) for s in P.splitlines(True) ])

上面的方法利用了re的sub方法,它在处理字符串时,每遇到一个匹配项,会调用参数中的方法来处理,可以看出,上面的方法是针对多行字符串来写的,当然,它也同样适用与单行字符串.


相关说明:

re.split(pattern, string, maxsplit=0)
    Split the source string by the occurrences of the pattern,
    returning a list containing the resulting substrings.

re.sub(pattern, repl, string, count=0)
    Return the string obtained by replacing the leftmost
    non-overlapping occurrences of the pattern in string by the
    replacement repl.  repl can be either a string or a callable;
    if a callable, it's passed the match object and must return
    a replacement string to be used.

标签:


Comments: 发表评论



<< Home

This page is powered by Blogger. Isn't yours?