2009-08-14 3 views
1

Ich möchte Punkte in Akronyme, aber nicht in Domänennamen in einer Python-Zeichenfolge entfernen. Zum Beispiel wollen ich die ZeichenfolgeWas ist die Regex zum Entfernen von Punkten in Akronymen, aber nicht in Domain-Namen?

'a.b.c. [email protected] http://www.test.com' 

'abc [email protected] http://www.test.com' 

Die nächstgelegene regex ich bisher

ist
re.sub('(?:\s|\A).{1}\.',lambda s: s.group()[0:2], s) 

die

führt zu
'ab.c. [email protected] http://www.test.com' 

Es machte zu werden scheint das f oder die oben regex arbeiten, muss ich die Regex

(?:\s|\A|\G).{1}\. 

ändern, aber es ist kein Ende der Spielmarker (\ G) in Python.

EDIT: Wie ich in meinem Kommentar erwähnt habe, haben die Strings keine spezifische Formatierung. Diese Zeichenfolgen enthalten informelle menschliche Konversationen und können daher null, eins oder mehrere Akronyme oder Domänennamen enthalten. Ein paar Fehler sind für mich in Ordnung, wenn es mich davor bewahren würde, einen "echten" Parser zu programmieren.

+4

IMHO ein regulärer Ausdruck ist nicht das richtige Werkzeug für Ihr Problem. Dies ist möglicherweise möglich, führt jedoch zu übermäßig komplexem Code. Ich würde einen traditionelleren Ansatz verwenden und einen Mix-Regexs- und Python-Code verwenden, um den String in seine Komponenten aufzuteilen (normaler Text, Akronyme, ...) und die Teile einzeln zu verarbeiten. Ausführlicher, aber auch wartbarer. – sebasgo

+0

Ich hätte wahrscheinlich erwähnen sollen, dass ich dies als Teil einer Reihe anderer Regex verwende, um eine Folge von Strings zu normalisieren, die informelle menschliche Konversationen darstellen. Ich kann ein paar Fehler tolerieren, wenn mich das vor einer gründlicheren Analyse bewahren würde. – ianalis

+1

Sie müssen das Problem besser angeben. Handelt es sich bei Ihren Daten immer um drei voneinander getrennte Teile, und möchten Sie nur den ersten Teil beeinflussen? Oder müssen Sie dies auf beliebigen Text anwenden? Wenn das später, wie würden Sie ein Akronym definieren? Nur einzelne Buchstaben? Wenn ja, was erwartest du mit http://a.b.example.com? Oder möchten Sie eingebettete Punkte entfernen, außer wenn Sie wissen, dass sie Teil eines Domänennamens sind? Aber das wirft nur die Frage auf: Wann ist es Teil eines Domain-Namens: After @ oder http: //? Was ist mit ssh: oder anderen URL-Schemas? Einmal definiert, wäre jeder von diesen eine einfache Regex. – MtnViewMark

Antwort

1

Die für mich gearbeitet folgenden (mit Dank an Bart für seine Antwort):

re.sub('\.(?!(\S[^. ])|\d)', '', s) 

Dieser eine Punkt nicht entfernt wird, wenn es das erste Zeichen in einem Wort oder ein Akronym ist.

2

Ich schlage vor, Sie teilen die Zeichenfolge bei '@' (oder was auch immer Zeichen Sinn macht), die Ersetzung im ersten Teil, dann setzen Sie die Zeichenfolge wieder zusammen. Ich denke, das zeigt die Absicht des Codes besser als eine komplexe Regexp. So etwas wie dies vielleicht:

string='a.b.c. [email protected] http://www.test.com' 
left, rest = string.split("@",1) 
left = left.replace(".","") 
result="%[email protected]%s" % (left, rest) 
2

Sie einfach DOTS entfernen können, die nicht zwei haben [az] Buchstaben (oder mehr) vor ihnen:

\.(?![a-zA-Z]{2}) 

Aber das wird natürlich auch entfernen der erste Punkt von der folgenden Adresse:

[email protected]

Sie konnten das Problem beheben, indem tun:

\.(?![a-zA-Z]{2}|[^\[email protected]]*[email protected]) 

aber ich bin mir sicher, es wird noch viele solcher Eckfälle geben.

+0

Danke für diesen Vorschlag. Dies war die Grundlage meiner Antwort. Es ist mir schon in den Sinn gekommen, aber ich irre mich, es nicht zu verfolgen. – ianalis

5

Wenn Ihre Daten immer so formatiert sind, teilen Sie Ihre Daten in drei Teile auf, indem Sie den Speicherplatz teilen.

Dann ist es ziemlich trivial, die Perioden aus dem ersten Element zu entfernen und Join zu verwenden, um die Teile erneut zu erstellen.

+1

Es ist nicht immer so formatiert. Ich werde es in informellen menschlichen Gesprächen verwenden, wie in meinem neu hinzugefügten Kommentar erwähnt. – ianalis

0

nicht so elegant wie ein einfaches re.sub(), aber versuchen Sie dies:

import re 

s='a.b.c. [email protected] http://www.test.com' 
m=re.search('(.*?)(([a-zA-Z]\.){2,})(.*)', s) 

if m: 
    replacement=''.join(m.group(2).split('.')) 
    s=m.group(1)+replacement+m.group(4) 

print s 

Es geht davon aus, dass es kein pro String mehr als ein Akronym ist, aber man kann es immer wiederholt ausgeführt werden.

1

Eine nicht regex Weise:

>>> S = 'a.b.c. [email protected] http://www.test.com' 
>>> ' '.join(w if '@' in w or ':' in w else w.replace('.', '') for w in S.split()) 
'abc [email protected] http://www.test.com' 

(Erfordert Räume auf aufzuspalten, obwohl - wenn Sie also so etwas wie Kommata ohne Leerzeichen hatte, konnte es einige verpassen.)

Verwandte Themen