2016-01-01 14 views
7

Devo contrassegnare i contesti negativi in ​​una frase. L'algoritmo è la seguente:Come modificare il testo che corrisponde a una particolare espressione regolare in Python?

  1. Rileva un negatore (non/mai/non è/non/etc)
  2. Rileva una clausola che termina la punteggiatura (;:.!?)
  3. Aggiungere _NEG a tutte le parole tra questo.

Ora, ho definito una regex di cogliere tutte queste occorrenze:

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 

posso rilevare e sostituire il gruppo abbinato. Tuttavia, non so come ricreare la frase completa dopo questa operazione. Anche per più corrispondenze, match.groups() mi dà output errato.

Per esempio, se la mia frase di ingresso è:

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

uscita dovrebbe essere:

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 . 

Come posso fare questo?

risposta

4

Prima di tutto è meglio cambiare il negativo look-ahead (?![.:;!?]).)* ad una classe di caratteri negata.

([^.:;!?]*) 

Quindi è necessario utilizzare nessuno gruppo di cattura e rimuovere quelli in più per le parole negative perché avete circondato dal 3 Gruppo di cattura, lo farà rendimenti 3 partita delle tue parole negative come not. quindi è possibile utilizzare re.findall() per trovare tutte le partite:

>>> 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', '.')] 

o per la sostituzione delle parole è possibile utilizzare re.sub con una funzione lambda come il sostituto:

>>> 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." 

Si noti che per catturare la punteggiatura è necessario per metterlo anche in un gruppo di cattura. Quindi è possibile aggiungerlo alla fine delle frasi in re.sub() dopo la modifica.

+1

Questo funziona perfettamente! Per quanto riguarda le punteggiature, potrei anche eseguire un semplice tokenizer sul testo perché dovrò differenziare tra loro ed emoticon lo stesso. Grazie! – Avijit

Problemi correlati