2016-08-12 4 views
3

Ich möchte für natürliche Zahlen zu wiederholen und alle von ihnen zu fangen wiederholen.Wiederholen von Captures in Python seltsames Ergebnis

import re 
r = "the ((sixty|six)[ -]+)+items" 
s = "the sixty six items" 
re.findall(r, s) 
# [('six ', 'six')] 

Es entspricht "sechs" 2 mal, während es beobachtet werden kann, dass es nie auf "sechs sechs" hätte passen können; stattdessen musste es auf "sechsundsechzig" abgestimmt sein, aber die Aufnahme kehrt zurück ("sechs", "sechs").

Was passiert hier und wie kann ich zurückkehren ('sechzig', 'sechs')?

+0

'es nie auf "sechs sechs"' angepasst haben könnte ... ja es kann, '(sechzig | sechs)' bedeutet Spiel 'sixty' _or_' sechs '. –

+0

@TimBiegeleisen Falsch, denn wenn sie nacheinander aufeinander abgestimmt werden müssen, wo wird die "ty" im Sechs-Sechs-Fall abgeglichen? – PascalVKooten

Antwort

3

re.search nur finden s das erste, was dem Muster entspricht, sucht es nicht nach weiteren Übereinstimmungen, wenn es einmal gefunden wurde. Sie erhalten ('six ', 'six'), weil Sie eine Erfassungsgruppe in einem anderen verschachtelt haben; Die 'six ' entspricht der äußeren Gruppe und die 'six' (ohne Leerzeichen) entspricht der inneren Gruppe.

Sie können tun, was Sie wollen, indem Sie zwei nicht verschachtelte Capture-Gruppen in einigen Nicht-Capture-Gruppen verwenden, die die (?:...)-Syntax verwenden.

import re 

r = "the (?:(?:(sixty)|(six))[ -]+)+items" 
s = "the sixty six items" 
m = re.search(r, s) 
if m: 
    print(m.groups()) 

Ausgang

('sixty', 'six') 

Dieses ein Tupel von zwei Elementen zurückgibt, weil wir zwei Capture-Gruppen im Muster haben.

Hier ist eine längere Demo.

import re 

pat = re.compile("the (?:(?:(sixty)|(six))[ -]+)+items") 

data = (
    "the items", 
    "the six items", 
    "the six six items", 
    "the sixty items", 
    "the six sixty items", 
    "the sixty six items", 
    "the sixty-six items", 
    "the six sixty sixty items", 
) 

for s in data: 
    m = pat.search(s) 
    print('{!r} -> {}'.format(s, m.groups() if m else None)) 

Ausgang

'the items' -> None 
'the six items' -> (None, 'six') 
'the six six items' -> (None, 'six') 
'the sixty items' -> ('sixty', None) 
'the six sixty items' -> ('sixty', 'six') 
'the sixty six items' -> ('sixty', 'six') 
'the sixty-six items' -> ('sixty', 'six') 
'the six sixty sixty items' -> ('sixty', 'six') 
+0

Wie skaliert das, wenn wir auch "sieben" und "siebzig" einschließen? Irgendwie bekomme ich viele 'None'-Matches dazwischen. Mit 'r =" die (? :(?: (Sechzig) | (sechs) | (sieben) | (siebzehn)) [-] +) + Artikel "' – PascalVKooten

+0

@PascalvKooten: Dieses Muster hat 4 Capture-Gruppen, also wann Sie suchen mit ihm '.groups' gibt Tupel von 4 Elementen zurück, eines für jede der Sammelgruppen in Ihrem Muster. –

+0

Also ich denke, ich werde die "-teens", "-ties" und diejenigen ohne Suffix gruppieren und dann 3 mögliche Gruppen da haben .... auch danke für die Erklärung. – PascalVKooten

2

Wenn Sie (group)+ verwenden, wird nur der letzte übereinstimmende Text in der Gruppe erfasst.

Sie sollten findall mit etwas anderen Regex verwenden.

s = 'the sixty six items' 

>>> if re.match(r'the (?:(?:sixty|six)[ -]+)+items', s): 
...  re.findall(r"\b(sixty|six)[ -]+(?=.*\bitems\b)", s) 
... 
['sixty', 'six'] 

Ihre Frage hat diesen Code:

>>> r = "the ((sixty|six)[ -]+)+items" 
>>> s = "the sixty six items" 
>>> re.findall(r, s) 

Welche [('six ', 'six')] wegen quantifier nach Ihrer Gruppe

findall Wert 2 Werte dh ((sixty|six)[ -]+)+ verwendet zurückkehrt, die

    sind
  1. captured group #1 ist "six " (einen Raum hier beachten aufgrund [ -]+ in Ihrem ersten Gruppe)
  2. captured group #2 ist "six" (innere Gruppe dh (sixty|six))
+0

Hmmm, naja das eigentliche Beispiel ist, wo dies nur ein Teil davon ist; 'findall' gibt auch' ("vier", "vier") zurück. ' – PascalVKooten

+0

Ich habe die Frage aktualisiert. – PascalVKooten

+0

Aber diese Gruppe # 0 hätte nicht "sechs" sein können, also scheint es etwas Merkwürdiges vor sich zu gehen? – PascalVKooten

0

Try regex

re.findall('(six\w*)', s) 
+0

Könnte möglicherweise falsche Treffer erhalten, z.B. Ich will nicht "sechzehntel" schlagen. – PascalVKooten

1

Verwenden \b Behauptung: Hoffnung das hilft.

>>> s = "the sixty six items" 
>>> print(re.findall(r'(?is)(\bsixty\b|\bsix\b)',s)) 
['sixty', 'six'] 

\b Behauptung wird falschen Treffer vermeiden, zum Beispiel: Wenn Sie sechzehn hinzufügen und wollen nicht

Ohne \b

>>> s = "the sixty sixteen six items" 
>>> print(re.findall(r'(?is)(sixty|six)',s)) 
['sixty', 'six', 'six'] 

Mit \b (Vorteile)

>>> s = "the sixty sixteen six items" 
>>> print(re.findall(r'(?is)(\bsixty\b|\bsix\b)',s)) 
['sixty', 'six'] 
Übereinstimmen