2016-07-06 12 views
6

Ich versuche, die folgenden mit einem regulären Ausdruck zu tun:Python regulärer Ausdruck alles, aber bestimmte Worte zu ersetzen

import re 
x = re.compile('[^(going)|^(you)]') # words to replace 
s = 'I am going home now, thank you.' # string to modify 
print re.sub(x, '_', s) 

Das Ergebnis I erhalten:

'_____going__o___no______n__you_' 

Das Ergebnis mag ich ist:

'_____going_________________you_' 

Seit der ^ kann nur in Klammern verwendet werden [], dieses Ergebnis macht Sinn, aber ich bin mir nicht sicher, wie ich es sonst machen könnte.

Ich versuchte sogar '([^g][^o][^i][^n][^g])|([^y][^o][^u])', aber es ergibt '_g_h___y_'.

+1

Nur zu FYI: Der Grund, warum Ihr '[^ (going) |^(you)]' scheitert, ist, dass die '[..]' -Syntax zu * nur einem Zeichen führt *. Das "^" am Anfang ist etwas Besonderes und bedeutet in der Tat "nicht", aber alles danach wird als eine benutzerdefinierte Menge von Zeichen betrachtet: '()^ginouy |'. – usr2564301

Antwort

5

Nicht ganz so einfach wie es zuerst erscheint, denn es gibt kein "nicht" in REs außer ^ innerhalb [ ] das nur mit einem Zeichen übereinstimmt (wie Sie gefunden haben). Hier ist meine Lösung:

import re 

def subit(m): 
    stuff, word = m.groups() 
    return ("_" * len(stuff)) + word 

s = 'I am going home now, thank you.' # string to modify 

print re.sub(r'(.+?)(going|you|$)', subit, s) 

Gibt:

_____going_________________you_ 

zu erklären. Der RE selbst (ich verwende immer rohe Zeichenketten) entspricht einem oder mehreren beliebigen Zeichen (.+), ist aber nicht gierig (?). Dies wird in der ersten Klammergruppe (den Klammern) erfasst. Danach folgt entweder "going" oder "you" oder das Ende der Zeile ($).

subit ist eine Funktion (Sie können es alles im Rahmen des Grund nennen), die für jede Substitution aufgerufen wird. Ein Übereinstimmungsobjekt wird übergeben, aus dem die erfassten Gruppen abgerufen werden können. Die erste Gruppe benötigen wir nur die Länge von, da wir jedes Zeichen durch einen Unterstrich ersetzen. Die zurückgegebene Zeichenfolge ersetzt die Zeichenfolge, die dem Muster entspricht. Hier

3

ist ein regex Ansatz:

>>> re.sub(r'(?!going|you)\b([\S\s]+?)(\b|$)', lambda x: (x.end() - x.start())*'_', s) 
'_____going_________________you_' 

Die Idee ist, dass, wenn Sie mit Worten zu tun und man sie ausschließen möchten oder usw. Sie, dass die meisten der regex Motoren merken müssen (die meisten sie verwenden traditionelle NFA) analysieren Sie die Zeichenfolgen nach Zeichen. Und hier, da Sie zwei Wörter ausschließen wollen und ein negatives Lookahead verwenden möchten, müssen Sie die erlaubten Strings als Wörter definieren (mit Wortgrenzen) und da in Sub die passenden Muster durch die Ersetzungszeichenfolge ersetzt werden, können Sie nicht einfach die _, denn in diesem Fall wird ein Teil wie I am durch 3 Unterstriche ersetzt (I, '', 'am'). Sie können also eine Funktion verwenden, um als zweites Argument von sub zu übergeben und die _ mit der Länge der zu ersetzenden übereinstimmenden Zeichenfolge zu multiplizieren.

+0

Das letzte '.' vor dem Ende des Textes? Auch nicht genug Unterstriche zwischen "Going" und "You". – cdarke

+0

@cdarke Ja, scheint so, lass mich überprüfen! – Kasramvd

+1

@cdarke Sie können die Bearbeitung jetzt überprüfen ;-) – Kasramvd

Verwandte Themen