2016-07-12 9 views
1

Ich muss IDs aus einer Zeichenfolge des folgenden Formats extrahieren: Name ID, wo die beiden durch Leerraum getrennt sind.Bedingte Regex: wenn A und B, wählen Sie B

Beispiel:

'Riverside 456' 

Manchmal wird die ID mit dem nachgestellten Buchstaben A oder B (durch Leerzeichen getrennt):

'Riverside 456 A' 

In diesem Fall habe ich ‚456 extrahieren möchten A 'statt nur' 456 ': Ich habe versucht, dies mit dem folgenden Regex zu erreichen:

(\d{1,3}) | (\d{1,3}\s[AB]) 

Der bedingte Operator | funktioniert in dieser Einstellung nicht ganz, da ich nur numerische IDs erhalte. Irgendwelche Vorschläge, wie man Regex in dieser Einstellung richtig einrichtet?

Jede Hilfe wäre willkommen.

+0

ist das die ganze Zeile, wenn ja, können Sie einen Teilstring? – depperm

+0

Können Sie nicht eine Null oder einen Scheck (?) Es scheint, der Leerraum wäre 0 oder 1 auch – PyNEwbie

+0

versuchen ''(\ d {1,3} [\ AB] *)' ' – alexpeits

Antwort

3

Versuchen Sie einfach, die Reihenfolge der Anweisungen umzukehren, um die spezifischere zuerst zu haben. Ie .:

 (\d{1,3}\s[AB]) | (\d{1,3}) 
+0

Alternation wie diese verliert immer in der Leistung zu optionalen Gruppen. –

+0

Wie ich schon sagte: Diese Lösung ist nicht optimal in Bezug auf die Regex-Leistung aufgrund von Backtracking, die hart arbeiten muss, um 1 bis 3 Ziffern in beiden Zweigen zu prüfen. Dies ist eine lesbare Lösung für Anfänger, aber das ist definitiv eine schlechte Übung in der Produktion. –

2

Ihr (\d{1,3})|(\d{1,3}\s[AB]) werden die erste Filiale wie in einem NFA Regex immer übereinstimmen, wenn der Wechsel Gruppe nicht auf beiden Seiten verankert ist, der erste Zweig, „gewinnt“, und der Rest des Zweiges nach rechts entspricht nicht getestet gegen.

können Sie eine optionale Gruppe verwenden:

\d{1,3}(?:\s[AB])? 

Siehe the regex demo

ein $ at the end hinzufügen, wenn der Wert, den Sie müssen immer am Ende der Zeichenfolge ist.

Wenn mehr als 1 Leerzeichen vorhanden sein können, fügen Sie + nach \s hinzu. Oder *, wenn es keine weiteren Whitespaces geben kann.

Beachten Sie, dass der letzte ? Quantifizierer ist gierig, also, wenn es ein Leerzeichen und A oder B gibt, werden sie Teil des Spiels sein.

Siehe Python demo:

import re 
rx = r'\d{1,3}(?:\s[AB])?' 
s = ['Riverside 456 A', 'Riverside 456'] 
print([re.search(rx, x).group() for x in s]) 
+0

@chizze Bitte überprüfen die Antwort und bitte lassen Sie wissen, ob es für Sie funktioniert oder nicht, und wenn etwas mehr Klärung benötigt. –

+0

Vielen Dank für Ihre Antwort! Sehr gründlich und erklärend. Ich habe es implementiert und es funktioniert gut. Wusste nicht, dass die optionale Gruppe enthalten sein wird, wenn sie gefunden wird, das ist gut zu wissen. – chizze

2

Wenn Sie einen optionalen Teil, die Sie umfassen möchten vielleicht, aber nicht unbedingt benötigen, Sie könnten nur eine „höchstens einmal“ quantifier verwenden:

Riverside (\d{1,3}(?: [AB])?) 

Die ?: markiert Gruppen als "nicht erfassend", daher werden sie nicht zurückgegeben. Und die ? sagt ihm, es entweder einmal zu vergleichen oder es zu ignorieren.

+2

Ich denke, es muss erfasst werden, aus der Frage ** In diesem Fall möchte ich '456 A' extrahieren ** – PyNEwbie

+1

Eigentlich glaube ich, 'Riverside' kann nicht fest codiert werden, OP muss die ID aus einer beliebigen Zeichenfolge extrahieren. –

+0

Nun ... ohne weitere Informationen ist dies genauso eine gültige Annahme wie meine. ;) Der reguläre Ausdruck ohne irgendeine Art von Präfix kann alle möglichen Dinge zusammenbringen, außer was OP eigentlich haben möchte. Und schließlich ist es nur eine mögliche Lösung. Und 'Riverside' durch' \ w + 'zu ersetzen, ist ziemlich einfach von hier. –

0
import re 

pattern = re.compile(r'(\d{1,3}\s?[AB]?)$') 
print(pattern.search('Riverside 456').group(0)) # => '456' 
print(pattern.search('Riverside 456 A').group(0)) # => '456 A' 
0

Sie Wechsel

p = re.compile('''(\d{1,3}\s[AB]|\d{1,3})$''') 

NB $ oder vielleicht \s am Ende nutzen können (außerhalb der Gruppe) ist wichtig, sonst wird es sowohl 123 C und 1234 als 123 zu erfassen, anstatt nicht übereinstimmen.

Verwandte Themen