2016-09-09 2 views
1

Ich möchte eine Zeichenfolge von , ->, => oder solche mit mehreren Räumen eingewickelt spalten, was bedeutet, dass ich zwei Punkte zu bekommen, she und he, aus den folgenden Zeichenfolgen nach geteilt wird:
"she he", "she he", "she he ", "she he ", "she->he", "she ->he", "she=>he", "she=> he", " she-> he ", " she => he \n"Warum führt diese Regex zu vier Elementen?

I mit diesem haben versucht:

re.compile("(?<!^)((\\s*[-=]>\\s*)|[\\s+\t])(?!$\n)(?=[^\s])").split(' she -> he \n') 

Was bekomme ich eine Liste mit vier Elemente: [' she', ' -> ', ' -> ', 'he \n'].

Und dafür

re.compile("(?<!^)((\\s*[-=]>\\s*)|[\\s+\t])(?!$\n)(?=[^\s])").split('she he') 

ich dieses: ['she', ' ', None, 'he'].

Warum gibt es vier Elemente? Und wie kann ich nur zwei ohne die mittleren zwei bekommen?

+2

'split' bewahrt den Inhalt Ihrer Einfanggruppen. Lass sie alle nicht erfassen. –

+0

Können Sie einen string.strip() nicht ausführen, bevor Sie die Zeichenfolge an die pattern.split übergeben? Macht es ein bisschen sauberer. – sisanared

+0

Versuchen Sie es mit 're.findall (...)': 're.findall ('\ w +'," sie -> er \ n ")' wird '['sie', 'er']'. – acw1668

Antwort

3

Wenn Sie nur Ihre Eingabezeichenfolge entfernen können. Aus Ihrer Beschreibung, alles, was Sie brauchen, auf die Worte zu teilen ist entweder \s+ oder \s*->\s* oder \s*=>\s*

hier ist also meine Lösung:

p = re.compile(r'\s*[-=]>\s*|\s+') 
input1 = "she he" 
input2 = " she -> he \n".strip() 

print p.split(input1) 
print p.split(input2) 

Die Ausgabe wäre nur ‚sie‘ und ‚er‘:

['she', 'he'] 
1

Wie bereits in den Kommentaren angegeben, wobei jedes Paar von Klammern in Ihrem regex bildet eine Capture-Gruppe, und jeder von denen wird durch die regex split() Funktion zurückgegeben. Gemäß der documentation,

Wenn einfangende Klammern im Muster verwendet werden, dann werden die Texte aller Gruppen im Muster auch als Teil der Ergebnisliste zurückgegeben.

Python-reguläre Ausdrücke verfügen über eine Funktion für nicht erfassbare Klammern. Sie verwenden (?: anstatt nur ( für die öffnende Klammer zu gruppieren ohne zu erfassen.

>>> re.compile("(?<!^)((\\s*[-=]>\\s*)|[\\s+\t])(?!$\n)(?=[^\s])").split('she he') 
['she', ' ', None, 'he'] 
>>> re.compile("(?<!^)(?:(?:\\s*[-=]>\\s*)|[\\s+\t])(?!$\n)(?=[^\s])").split('she he') 
['she', 'he'] 

Es ist nicht ganz klar, warum Sie eine Registerkarte explizit in der Zeichenklasse mit \s umfassen; Die \s enthält bereits Registerkarte als eines der vielen Leerzeichen, die es entspricht.

Es ist auch nicht klar, was Sie erwarten $\n zu entsprechen. $ ist das Ende der Zeile und \n ist ein buchstäbliches Newline-Zeichen, so dass Sie versuchen, mit Zeilenumbrüchen umzugehen; aber $ allein deckt das schon ab. Der einzige Unterschied zwischen $ und $\n ist, dass wenn das Ende der Zeichenfolge (die letzte Zeile in einer mehrzeiligen Zeichenfolge) nicht Newline-terminiert ist, das letztere nicht übereinstimmen wird.

Die (?<!^) ist auch eigentümlich - eine bessere Möglichkeit zu vermeiden, eine leere Zeichenfolge zu finden, ist sicherzustellen, dass Ihr regulärer Ausdruck immer mit etwas übereinstimmt.

Von Ihren Anforderungen entspricht, scheint es, dass

re.compile(r'\s*[-=]>\s*|\s+').split('he she') 

tun würde, was Sie kurz und bündig und leserlich wollen. Dies entspricht einem ASCII-Pfeil (Einzel- oder Doppelstopp) mit optionalem Leerzeichen auf beiden Seiten, oder wenn dies fehlschlägt, fällt es in eine Folge von Leerzeichen zurück.

+0

Gute Antwort, lässt ihn immer noch mit leeren Strings, wenn auf dem obigen Beispiel 'sie verwendet -> er \ n'. Ich schlage vor, "filter()" auf das Ergebnis zu verwenden. – Toastgeraet

+0

Vielen Dank für Ihre ausführliche Erklärung. – lerner

0

Bei jeder Verwendung von Klammern "()" erstellen Sie eine Erfassungsgruppe. Eine einfangende Gruppe ist Teil eines Spiels. Eine Übereinstimmung bezieht sich immer auf die vollständige Regex-Zeichenfolge. Deshalb erhalten Sie 4 Ergebnisse.

Dokumentation sagt: "If capturing parentheses are used in pattern, then the text of all groups in the pattern are also returned as part of the resulting list."

Sie könnten versuchen, die Gruppen "nicht-Capturing" machen als rawing vorgeschlagen. Tun Sie dies, indem Sie einfach "?:" Innerhalb der Klammern vorgeben, die nicht erfasst werden sollen.

würde ich nur die Klammern ganz auslassen:

res = re.compile("\\s*[-=]>\\s*|\\s*").split(' she -> he \n') 
res = filter(None, res) 
res = list(res) 

Ausgang:

['she', 'he'] 
Verwandte Themen