1

我想搜索和替换 <> 之外的所有匹配项。我可以假设所有括号都匹配。例如,我想用 '*' 替换 'BLOCK':

BLOCKaaa<BLOCKaaaa>aaaaa<>BLOCKzzzBLOCKBLOCK

会成为:

*aa<BLOCKaaaa>aaaaa<>*zzz**

我尝试了以下方法:

- 在行首添加>,在行尾添加<,称之为LINEwith><

-跑:

re.sub('(>[^<>]*)(BLOCK)+? ([^<>]*<?)', '\\1*\\3', LINEwith><)

但它给了我这个:

'>*aaa<BLOCKaaaa>aaaaa<>BLOCKzzzBLOCK*<'

我不确定如何替换 ><

有人可以帮我弄这个吗?或者建议一种更好的方法。

4

2 回答 2

4

由于您可以假设括号始终匹配,因此以下应该有效。

re.sub(r'BLOCK(?=[^>]*(<|$))', '*', line)

这也假设不能有嵌套的括号。

这使用前瞻来确保>在下一个<字符或字符串结尾之前没有字符。由于正在使用前瞻,因此正则表达式实际匹配的唯一文本是BLOCK,因此替换被简化为,'*'因为不再有任何捕获组。

这是一个最多可以使用一级嵌套括号的版本:

BLOCK(?=([^<>]*(<(<[^>]*>|[^<>])*>)?)*$)

例子:

>>> p = re.compile(r'BLOCK(?=([^<>]*(<(<[^>]*>|[^<>])*>)?)*$)')
>>> p.sub('*', 'BLOCK<BLOCK<BLOCK>>BLOCK<BLOCK>BLOCKzzzBLOCKBLOCK')
'*<BLOCK<BLOCK>>*<BLOCK>*zzz**'

正如您所看到的,正则表达式并不是非常适合嵌套数据结构。

于 2012-06-15T20:34:57.250 回答
0

如果括号是嵌套的,则不能使用正则表达式。来点split-fu怎么样?

def replace_outside(string, original, replacement):
    level = 0  #the level of nesting - 0 is outside
    result = [] #a temp list holding the result
    while string:
        #split the string until the first '<', save everything before that in
        #current and process the rest in the next iteration
        splitstr = string.split("<", 1)
        if len(splitstr) == 1: current, string = string, ""
        else: current, string = tuple(splitstr)
        if level == 0:
            #we're outside - replace everything in current string
            current = current.replace(original, replacement)
        else:
            #decrease the level by the number of closing brackets in current
            level -= current.count(">")
            if level == 0:
                #everything after the last '>' is outside
                inner, outer = current.rsplit(">", 1)
                #replace outer and join with inner again
                outer = outer.replace(original, replacement)
                current = '>'.join([inner, outer])
        #append the string to the result list and increase level by one
        result.append(current)
        level += 1
    #return the result list joined by the '>' we split it by
    return '<'.join(result)

(如果有任何不匹配的括号,这显然会失败。)

于 2012-06-15T21:28:19.963 回答