5.修改字符串
到目前为止,我们只是知道了如何在静态的字符串上执行搜索。正则表达式也可以通过使用下述模式方法修改字符串:
方法/属性 | 功能 |
split() | 在正则表达式匹配的地方进行分割,返回一个列表 |
sub() | 找到所有匹配的子字符串,并替换为新的子串 |
subn() | 和sub()方法做同样的事情,但返回新的字符串以及替换的数目 |
5.1.分割字符串
模式对象的split()方法在正则表达式匹配的地方进行分割,并将分割的结果作为列表返回。它和Python字符串的split()方法有些类似, Python字符串的split()方法支持按照空格或者按照固定的字符串分割,但是它提供更广泛的分隔符。正如你所预想的,它同时也提供一个模块级别的函数re.split()。
split(string [, maxsplit = 0])
按照正则表达式匹配来分割字符串。如果在正则表达式中使用了捕获组,那么它们的内容也将作为一个列表的一部分返回。如果maxsplit不为0,表示至多有maxsplit个分割会被处理。
你可以通过传入maxsplit参数来确定分割的数量,当maxsplit不为0时,最多有maxsplit个分割会被处理,剩下的字符串将会作为列表的最后一项返回。在下述例子中,分隔符是任意的非字母数字字符序列。
>>> p = re.compile(r'\W+') >>> p.split('This is a test,short and sweet,of split().') ['This', 'is', 'a', 'test', 'short', 'and', 'sweet', 'of', 'split', ''] >>> p.split('This is a test,short and sweet,of split().',3) ['This', 'is', 'a', 'test,short and sweet,of split().']有时候你不仅对分隔符之间的内容感兴趣,还对分隔符本身感兴趣。如果在正则表达式中使用捕获分组,那么它们的内容将作为列表的一部分返回,
对比下述例子:
>>> p = re.compile(r'\W+') >>> p2 = re.compile(r'(\W+)') >>> p.split('This... is a test.') ['This', 'is', 'a', 'test', ''] >>> p2.split('This... is a test.') ['This', '... ', 'is', ' ', 'a', ' ', 'test', '.', '']模块级别的函数re.split()除了将正则表达式作为第一参数外,其他是一样的。
>>> 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.',1) ['Words', 'words,words.']---------------------------------------------------------------------------------------------------------------------------------------------------
>>> p = re.compile('(blue|white|red)') >>> p.sub('colour','blue socks and red shoes') 'colour socks and colour shoes' >>> p.sub('colour','blue socks and red shoes',1) 'colour socks and red shoes'subn()方法与sub()功能一致,但是subn()方法会返回一个包含两个元素的元组:新的字符串和执行替换的次数:
>>> p = re.compile('blue|white|red') >>> p.subn('colour','blue socks and red shoes') ('colour socks and colour shoes', 2) >>> p.subn('colour','no colours at all') ('no colours at all', 0)空匹配只有在它们没有紧挨着前面的匹配时才会被替换掉:
>>> p = re.compile('x*') >>> p.sub('-','abxd') '-a-b-d-'如果 replacement 参数是一个字符串,那么之中的反斜杠都会被处理。比如 \n 将会被转换成一个换行符,\r会被 转换成回车,等等。未知的转义如 \j 保持原样。逆向引用,如 \6,则被 RE 中相应的捕获组匹配的内容所替换。这使你可以在替换后的字符串中插入一部分原字符串。
>>> p = re.compile('section{([^}]*)}',re.VERBOSE) >>> p.sub(r'subsection{\1}','section{First} section{Second}') 'subsection{First} subsection{Second}'还可以使用Python的扩展语法 (?P
>>> p = re.compile('section{ (?Preplacement参数也可以是一个函数,这可以让你实现更多的功能。如果replacement参数是一个函数,该函数将会在正则表达式模式每次不重复匹配的时候被调用。在每次调用时,函数会收到一个匹配对象的参数,因此你就可以利用这个对象去计算出新的字符串并返回它。[^}]*) }',re.VERBOSE) >>> p.sub(r'subsection{\1}','section{First}') 'subsection{First}' >>> p.sub(r'subsection{\g<1>}','section{First}') 'subsection{First}' >>> p.sub(r'subsection{\g }','section{First}') 'subsection{First}'
>>> def hexrepl(match): '''Return the hex string for a decimal number''' value = int(match.group()) return hex(value) >>> p = re.compile(r'\d+') >>> p.sub(hexrepl,'Call 65490 for printing, 49152 for user code.') 'Call 0xffd2 for printing, 0xc000 for user code.'当使用模块级函数re.sub()的时候,正则表达式模式同样作为第一参数传递。该模式可以是一个字符串或一个编译好的对象。如果你需要指定正则表达式编译标志,那么你必须使用后者;或者使用模式内嵌修正器,例如,sub("(?i)b+", "x", "bbbb BBBB") 返回 'x x'。