2016-07-19 8 views
0

Ich möchte Satzzeichen und Symbole vom Haupttext trennen, um sie als separate Token zu teilen. Ich habe eine Textdatei mit den folgenden Symbolen %&()+,-./:;=–‘’“”″ und ich möchte jedes Symbol durch \ssymbol\s ersetzen (die \s bedeutet ein Leerzeichen), und wenn zwei Symbole des gleichen Typs, z. .. treten nebeneinander auf, ich möchte sie durch \s..\s ersetzen. Dies ist, was ich bisher versucht:Ersetzen von Teilzeichenfolgen mit Leerzeichen + Teilzeichenfolge + Leerzeichen mit Regex Python3.x

>>> punc = "[%&\(\)\+,-./:;=–‘’“”″]+" 
>>> import re 
>>> pattern = re.compile(punc) 
>>> text = "hi. hi.. hi; hi;; 55% good& good&&" 
>>> text = re.sub(pattern, ' '+str(pattern)+' ', text) 

Wenn ich den Text drucken, erhalte ich folgendes:

>>> print(text) 
hi <_sre.SRE_Pattern object at 0x00000000035E14E0> hi <_sre.SRE_Pattern object at 0x00000000035E14E0> hi <_sre.SRE_Pattern object at 0x00000000035E14E0> hi <_sre.SRE_Pattern object at 0x00000000035E14E0> 55 <_sre.SRE_Pattern object at 0x00000000035E14E0> x <_sre.SRE_Pattern object at 0x00000000035E14E0> 

Aber ich möchte, dass die Ausgabe wie folgt sein:

hi . hi .. hi ; hi ;; 55 % good & good && 

Nach mehreren Versuchen habe ich festgestellt, dass ich den richtigen Regex nicht kompilieren kann. Ihre freundliche Hilfe wird sehr geschätzt!

Antwort

1

Der richtige Weg, um mit dem zu verfahren, was Sie versuchen zu tun, ist Capturing Groups zu verwenden. Auf diese Weise können Sie auf Ihre Übereinstimmung verweisen. Lassen Sie mich zunächst erklären, warum Ihr Versuch Ihnen die Ausgabe gab, die Sie gesehen haben.

Warum Sie sah, was du gesehen hast

In der re.sub Funktion, wenn Sie es ' '+str(pattern)+' ' als dritter Parameter geben, diese auf die Zeichenfolge ausgewertet wird " <_sre.SRE_Pattern object at some_memory_location> ", weil str(pattern) die Stringdarstellung des Objekts Muster kehrt, nicht von der Muster.

Nebenbei, auf Python 3.4 und 3.5, str(pattern) gibt re.compile('[%&\\(\\)\\+,-./:;=–‘’“”″]') für mich zurück, welche Version von Python verwenden Sie? Ist es vielleicht eine Version von Python 2?

Lösung

Wie ich vor erwähnt, erfordert Ihre Lösung unter Verwendung groups einzufangen. Um eine Gruppe zu bezeichnen, verwenden Sie einfach Klammern. In Ihrem Fall ist die Lösung einfach genug ist, weil Sie nur eine Gruppe benötigen:

>>> import re 
>>> pattern = re.compile(r"([%&\(\)\+,-./:;=–‘’“”″]+)") 

Hinweis für meinen Stringliteral, benutzen ich ein r vor Beginn der Zeichenfolge. Dies bezeichnet eine rohe Zeichenfolge, die bewirkt, dass die Zeichenfolge jede Escape-Sequenz ignoriert, wie von Python definiert. Eine Escape-Sequenz ist zum Beispiel eine Art '\t', die eine Registerkarte bezeichnet. Wenn Sie jedoch r'\t' verwenden, ist es die tatsächliche Zeichenfolge \t.

>>> text = "hi. hi.. hi; hi;; 55% good& good&&" 
>>> pattern.sub(r' \1 ', text) 
'hi . hi .. hi ; hi ;; 55 % good & good && ' 

Hinweis habe ich einfach die sub Methode des Musterobjekt statt der Modulebene Funktion re.sub. Es ist keine große Sache, aber es scheint mir nur sauberer zu sein. Auch für das Ersetzungsargument verwendete ich r' \1 '. Diese \1 bezieht sich auf die erste Gruppe von Ihrem Muster erfasst. Wenn Sie mehr als eine Gruppe hatten, könnten Sie etwas wie \2 \1 verwenden, wenn Sie beispielsweise ein Muster umkehren wollten. Das ist wieder eine Escape-Sequenz!

Eine mögliche Verbesserung

Es war unklar, in Ihrer Spezifikation, wie Sie mit mehr als 2 Zeichen behandeln wollten z.B. drei Zeichen. So würde Ihr Muster thusly mit dieser Situation umgehen:

>>> text2 = "hi. hi.. hi; hi;; 55% good& good&& hi &&& hello," 
>>> pattern.sub(r' \1 ', text2) 
'hi . hi .. hi ; hi ;; 55 % good & good && hi &&& hello , ' 

Vielleicht ist das, was Sie was, aber vielleicht möchten Sie prüfen, ‚& & &‘ als zwei verschiedene Begegnungen: ‚& &‘ und ‚&‘. Sie können mit dieser Situation doch mit quantifiers beschäftigen:

>>> pattern2 = re.compile(r'([%&\(\)\+,-./:;=–‘’“”″]{1,2})') 
>>> pattern2.sub(r' \1 ', text2) 
'hi . hi .. hi ; hi ;; 55 % good & good && hi && & hello , ' 

Anstatt das + Zeichen zu verwenden, die ein-oder-mehr bedeutet, können Sie die Klammer-Notation mehr feinkörnige Kontrolle haben. Beispiel: {1,3} entspricht 1 bis 3. {3} entspricht genau 3. {3,} entspricht 3 oder mehr.

+0

Vielen Dank für Ihre freundliche Hilfe. Ich dachte nicht, dass es so einfach ist, mein Problem zu lösen, wie Sie es angemessen erklärt haben. Bezüglich der Python-Version habe ich versucht, es unter 3.3.2 zu implementieren. Ich werde jetzt 3.4 installieren. In Bezug auf den Verbesserungsabschnitt wollte ich mich mit einem oder mehreren, sogar drei Charakteren des gleichen Typs befassen, die als eine Übereinstimmung behandelt werden, und das ist es, was Sie demonstriert haben. Nochmals vielen Dank für Ihre Hilfe. – Mohammed

+0

Allerdings möchte ich die Verwendung von '.sub (r '\ l', ...)' verstehen. – Mohammed

+0

@Mohammed Ah! Ja, das bezieht sich einfach auf die erste Gruppe, die von deinem Muster erfasst wurde! Wenn Sie mehrere Gruppen haben, können Sie auf die dritte als etwas wie 'Dies ist die dritte Gruppe: \ 3' verweisen. Siehe meine Bearbeitung. –