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ため、置換が簡略化されます。'*'

ネストされた角かっこの1レベルまで機能するバージョンは次のとおりです。

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 に答える