2016-01-01 1 views
7

Ich muss negative Kontexte in einem Satz markieren. Der Algorithmus geht wie folgt:Wie ändert man Text, der zu einem bestimmten regulären Ausdruck in Python passt?

  1. eine negator Detect (nicht/nie/nicht/nicht/etc)
  2. Detect eine Klausel endet Interpunktion (;.!?)
  3. hinzufügen _NEG zu allen Wörtern dazwischen. Jetzt

, ich habe einen regulären Ausdruck definiert, alle derartigen Vorkommnissen herauszupicken:

def replacenegation(text): 
    match=re.search(r"((\b(never|no|nothing|nowhere|noone|none|not|havent|hasnt|hadnt|cant|couldnt|shouldnt|wont|wouldnt|dont|doesnt|didnt|isnt|arent|aint)\b)|\b\w+n't\b)((?![.:;!?]).)*[.:;!?\b]", text) 
    if match: 
     s=match.group() 
     print s 
     news="" 
     wlist=re.split(r"[.:;!? ]" , s) 
     wlist=wlist[1:] 
     print wlist 
     for w in wlist: 
      if w: 
       news=news+" "+w+"_NEG" 
     print news 

Ich kann die ausgeglichene Gruppe erkennen und ersetzen. Ich weiß jedoch nicht, wie ich nach dieser Operation den kompletten Satz neu erstellen soll. Auch für mehrere Übereinstimmungen gibt match.groups() eine falsche Ausgabe.

Zum Beispiel, wenn mein Eingabesatz ist:

I don't like you at all; I should not let you know my happiest secret. 

ausgegeben werden soll:

I don't like_NEG you_NEG at_NEG all_NEG ; I should not let_NEG you_NEG know_NEG my_NEG happiest_NEG secret_NEG . 

Wie kann ich das tun?

Antwort

4

Zunächst ist es besser, die negative Vorausschau (?![.:;!?]).)* zu einer negierten Zeichenklasse zu ändern.

([^.:;!?]*) 

Dann brauchen Sie keine Capture-Gruppe zu verwenden und die überzähligen für Ihre negativen Worte zu entfernen, weil Sie es von 3 Capture-Gruppe umgeben sind, wird es zurückkehrt 3 Spiel Ihrer negativen Wörter wie not. dann können Sie re.findall() verwenden, um alle Spiele zu finden:

>>> regex =re.compile(r"((?:never|no|nothing|nowhere|noone|none|not|havent|hasnt|hadnt|cant|couldnt|shouldnt|wont|wouldnt|dont|doesnt|didnt|isnt|arent|aint)\b|\b\w+n't\b)([^.:;!?]*)([.:;!?\b])") 
>>> 
>>> regex.findall(s) 
[("don't", ' like you at all', ';'), ('not', ' let you know my happiest secret', '.')] 

Oder die Worte für das Ersetzen Sie re.sub mit einer Lambda-Funktion als Ersatzstoff verwendet werden können:

>>> regex.sub(lambda x:x.group(1)+' '+' '.join([i+'_NEG' for i in x.group(2).split()])+x.group(3) ,s) 
"I don't like_NEG you_NEG at_NEG all_NEG; I should not let_NEG you_NEG know_NEG my_NEG happiest_NEG secret_NEG." 

Beachten Sie, dass die Zeichensetzung für die Aufnahme benötigen Sie um es auch einer Fanggruppe zuzuordnen. Dann können Sie es am Ende Ihrer Sätze in re.sub() nach dem Bearbeiten hinzufügen.

+1

Das funktioniert perfekt! Was die Interpunktionen betrifft, kann ich auch einen einfachen Tokenizer auf dem Text ausführen, weil ich sowieso zwischen ihnen und Emoticons unterscheiden muss. Danke! – Avijit