2016-04-10 10 views
1

Ich habe ein Python 2.7-basiertes Programm, das Eingaben von einem Benutzer (entweder als Textdatei) oder direkt an der Eingabeaufforderung nimmt. Ich muss dann die Eingabe verifizieren, um sicherzustellen, dass sie im richtigen Format ist (und bei Bedarf mit Code neu formatieren).Verwenden nicht-gieriger Qualifier im regulären Ausdruck '*?'

Ideal Eingaben von Benutzer getrennte Wörter durch Kommas wie "blade, coffeen, cardiac". Aber ich wollte wird einen Scheck an setzen Eingaben im Format haben, damit "blade, coffeen, , cardiac" "blade,,cofeen,cardiac" "blade coffeen cardiac" usw.

Dies bedeutet, dass ich wahrscheinlich verwenden ein nicht-gieriger Qualifier wie *?. Obwohl ich grundlegende reguläre Ausdrücke kenne, ist diese bestimmte *? ein bisschen unklar. Im Moment verwende ich input_string.split(','), gefolgt von einem input_string.split(' '), um die verschiedenen Szenarien zu berücksichtigen, aber irgendwie fühlt es sich zu unpythonisch und chaotisch an. Ich frage mich auch, ob es Szenarien gibt, an die ich nicht gedacht habe und die den Code in der Produktion brechen werden.

im Internet sucht, um dieser Link https://docs.python.org/2/howto/regex.html hat einen ziemlich guten Job zu erklären, wie .*? funktioniert, und ich denke, wenn ich [, ]*? verwenden, dass mein Problem lösen kann.

Meine Frage ist:
1. Kann ich [, ]*? in meinem Fall verwenden, um die drei möglichen Szenarien für Eingaben zu berücksichtigen, die ich oben beschrieben habe?
Wie ich erwähnt habe, benutze ich string.split(',') nach der Validierung sowieso gefolgt von einem string.split(' '), aber eine regelmäßige Ausdrucksprüfung wird es sauberer machen. Auf jeden Fall würde ich gerne verstehen, wie genau sich das [, ]*? verhält, wenn es benutzt wird.

+1

Verwenden [Regex101] (https://regex101.com) Ihre RegEx zu testen. [Ihre Demo] (https://regex101.com/r/lF4zL7/1) – Druzion

+0

Was passiert, wenn der Eingang 'Thomas Edison, leonardo da vinci'? –

+0

@Druzion Vielen Dank für diesen Regex-Testlink. Es ist toll. – schywalker

Antwort

2

Ja, Sie können [, ]*? verwenden, wenn es Teil eines größeren regulären Ausdrucks ist. Und Sie können auch re.split() in Ihrem Fall verwenden und vermeiden, str.split() separat zu verwenden.

Allerdings müssen Sie nicht Notwendigkeit die ? greediness Modifikator zu verwenden, da Sie explizit für Wörter durch Leerzeichen und Komma getrennt zu prüfen. Die Wortzeichen passen nicht selbst zum [, ]* Set. In der Tat verbessert greedy matching die Leistung der Übereinstimmung hier, da der reguläre Ausdruck alle Leerzeichen und Kommata auf einmal und nicht nur einzeln aufnimmt und dann überprüfen muss, ob der Rest des Musters gleich nach dem übereinstimmt erste Leerzeichen oder Komma, dann ist das nächste Leerzeichen oder Komma usw.

folgende Werke, aber das Entfernen der ? macht also den Ausdruck Arbeit besser:

>>> import re 
>>> test = "blade, coffeen, , cardiac" 
>>> re.search('blade[, ]*?coffeen[, ]*?cardiac', test) 
<_sre.SRE_Match object at 0x100758c60> 
>>> re.search('blade[, ]*coffeen[, ]*cardiac', test) 
<_sre.SRE_Match object at 0x1026101d0> 

Sie werden das merken Problem, wenn Sie versuchen, re.split() zu verwenden und nur [, ]*? als das Muster verwenden:

>>> import re 
>>> test = "blade, coffeen, , cardiac" 
>>> re.split('[, ]*?', test) 
['blade, coffeen, , cardiac'] 

Wenn Spaltung von [, ]*? auch eine Null Breite Zeichenfolge (ein leerer String), um den Ausdruck übereinstimmt, und re.split() wird nicht geteilt allein auf leeren Saiten. Da er nicht gierig ist, hat eine Nullbreite den Test bestanden, und die Regex-Engine wird nicht nach mehr suchen.

Sie könnten es ändern, um mit +? (Match mindestens eine, oder mehr):

>>> re.split('[, ]+?', test) 
['blade', '', 'coffeen', '', '', '', '', '', '', 'cardiac'] 

Sie nun eine ganze Reihe von leeren Saiten in-zwischen bekommen, weil diejenigen, die verschiedenen Räume und Kommas trennen zwischen die Wörter.

Erst wenn ich den nicht-gierigen Modifikator entfernen wird es richtig Ihre Optionen in eine Liste aufzuschlüsseln, denn jetzt alle Leerzeichen und Kommas zwischen den Wörtern Spiel und verwendet werden, aufgeteilt auf:

>>> re.split('[, ]*', test) 
['blade', 'coffeen', 'cardiac'] 

Hab also keine Angst vor Gier, nicht wenn du eine bestimmte Teilmenge von Charakteren kombinierst, bei denen die Grenzen nicht verwechselt oder überbrückt werden können.

+0

das ist perfekt. Tolle Erklärung und gute Hinweise auf das leere String-Szenario. Ich wusste nicht über die re.split-Option, die einen regulären Ausdruck verwenden kann, um Strings zu teilen. Ich schätze die Lösung und die Tipps sehr. – schywalker