2012-04-15 2 views
1

Ich habe str1 und str2 unten, und ich möchte nur eine Regexp verwenden, die beide übereinstimmen. Im Falle von str1, möchte ich auch die Anzahl der QSFP-Ports in der Lage sein zu erfassenWie zeichne Strings mit * oder? mit Gruppen in Python reguläre Ausdrücke

>>> str1='''4 48 48-port and 6 QSFP 10GigE Linecard 7548S-LC''' 
>>> str2='''4 48 48-port 10GigE Linecard 7548S-LC''' 
>>> 

Ich möchte die Zahlen „4“ in der Lage sein zu erfassen, „48“, „6“ (falls vorhanden), und "7548". Aber ich kann "6" nicht mit dem "?" Metazeichen.

Wenn ich keinen metacharacter verwenden, funktioniert die Erfassung für str1, aber dann kann ich diese Regex verwenden, weil es wird nicht für str2 arbeiten:

>>> re.search(r'^(\d+)\s+(\d+)\s+.*(?:(\d+)\s+QSFP).*\s+(\d+)S-LC', str1, re.I|re.M).group(3) 
'6' 
>>> 

Es funktioniert sogar, wenn ich die „+“ verwenden, um ein Auftreten zeigen, aber auch hier diese nicht funktioniert für str2:

>>> re.search(r'^(\d+)\s+(\d+)\s+.*(?:(\d+)\s+QSFP)+.*\s+(\d+)S-LC', str1, re.I|re.M).group(3) 
'6' 
>>> 

Wenn ich „?“ um für 0 oder 1 Vorkommen zu entsprechen, schlägt die Aufnahme sogar für str1 fehl:

>>> re.search(r'^(\d+)\s+(\d+)\s+.*(?:(\d+)\s+QSFP)?.*\s+(\d+)S-LC', str1, re.I|re.M).group(3) 
>>> 
+1

Die Kombination von Quantifikatoren ist sinnlos ("0 oder mehr Kopien von 1 oder mehr Kopien von' \ d' "). Was versuchst du wirklich? – geekosaur

+0

Ich denke 're.search (r '(\ d +)', str1) .group (0)' ist ausreichend. – RanRag

+0

Ich möchte den Dezimalwert erfassen, wenn es in 'str1' erscheint, aber ich möchte nicht die Regex fehlschlagen, wenn es keinen Dezimalwert gibt. Also was ich wirklich will ist, dass dies unten den Dezimalwert erfasst: re.search (r '(\ d +)?', Str1) .group (1) –

Antwort

1

Ich bin nicht sicher, was genau Ihre Anforderung ist.

Ist es so etwas wie dieses:

>>> str1 = "hello 12 world" 
>>> str2 = "hello world" 
>>> obj = re.search(r'(\d+)',str1) 
>>> obj.group(0) 
'12' 

Jetzt in str2 Kontrolle, die keinen Dezimalwert enthält.

>>> obj = re.search(r'(\d+)',str2) 
>>> if obj is not None: 
...  print obj.group(0) 
... else: 
...  print "not found" 
... 
not found 
>>> 
+0

Ich habe versucht, meine zu vereinfachen Frage und jetzt sehe ich die Verwirrung, die es schaffen könnte. Das ist, was ich brauche: Ich habe str1 und str2 unten, und ich möchte nur eine Regexp verwenden, die beide übereinstimmen. Für str1 möchte ich die Anzahl der QSFP Ports erfassen >>> str1 = '' '4 48 48-Port und 6 QSFP 10GigE Linecard 7548S-LC' '' >>> str2 = '' '4 48 48-Port 10GigE Linecard 7548S-LC '' ' >>> >>> re.search (r'^4 \ s + 48 \ s +. * (?: (\ D +) \ s + QSFP). * - LC ', str1 (1) '6' >>> >>> re.search (r '^ 4 \ s s + QSFP)?. * - LC ', str1, re.I | re.M) .group (1) >>> –

+0

@ user1334085: Bitte fügen Sie diesen Kommentar in Ihre ursprüngliche Frage ein. – RanRag

+0

@ user1334085: und was ist die gewünschte Ausgabe für str2 – RanRag

2

Meine Interpretation des Problems war, dass OP einen regulären Ausdruck gesucht, die für beide Strings übereinstimmen, und geben die Anzahl in .group (1), wenn es (wie es funktioniert in str1) existiert. Ich glaube, das Problem war, dass er/sie nicht in der Lage war, sowohl die "6" in str1 einzufangen als auch str2.

Ich habe dies von einem schnellen Versuch und Irrtum:

>>> str1='''4 48 48-port and 6 QSFP 10GigE Linecard 7548S-LC''' 
>>> str2='''4 48 48-port 10GigE Linecard 7548S-LC''' 
>>> re.search(r'^4\s+48\s+.*(?:(\d+)\s+QSFP)|.*-LC', str1, re.I|re.M).group(1) 
'6' 
>>> re.search(r'^4\s+48\s+.*(?:(\d+)\s+QSFP)|.*-LC', str2, re.I|re.M).group(1) 
>>> # no error returned, implying a match was found. 

Der Unterschied ist, dass ich „oder“ Nicht-Erfassung Pars mit *

Leider ist dies die Regex macht noch schwieriger. zu verstehen, aber vielleicht wird es für dich funktionieren.

(der Vollständigkeit halber bearbeitet)

0

ich glaube, das Problem ist, dass die .* ist das QSFP Bit auffressen, und wegen der ? gibt es keinen Anreiz für die es immer wieder ansetzen zu. Das .* zu einem nicht-gierigen .*? (überraschend - für mich zumindest) zu ändern, hat nicht geholfen. Das Verschieben der .* innerhalb der Nicht-Erfassungsgruppe tut Hilfe, aber:

>>> re.match(r'^4\s+48\s+(?:.*(\d+)\s+QSFP)?.*-LC', str1, re.I|re.M).group(1) 
'6' 
>>> re.match(r'^4\s+48\s+(?:.*(\d+)\s+QSFP)?.*-LC', str2, re.I|re.M).group(1) 
>>> 
+0

Cool !!! Das hat mein Problem gelöst. Ich hatte es anfangs versucht. um es nicht gierig zu machen und es hatte auch nicht zu meiner Überraschung funktioniert. Aber deine Lösung funktioniert perfekt. Vielen Dank. –

1

I want to be able to capture the numbers "4", "48", "6" (if present), and "7548". But I am unable to capture "6" using the "?" metacharacter.

Sie können Ihr Leben vereinfachen, wenn Sie regex vermeiden, da Ihre Frage ist sehr einfach.

str1='''4 48 48-port and 6 QSFP 10GigE Linecard 7548S-LC''' 
str2='''4 48 48-port 10GigE Linecard 7548S-LC''' 
lines = [str1,str2] 
nums = [] 
for l in lines: 
    r = [] 
    bits = l.split() 
    last_num = bits.pop()[:-4] 
    _ = [r.append(i) for i in bits if i.isdigit()] 
    r.append(last_num) 
    nums.append(r) 

>>> nums 
[['4', '48', '6', '7548'], ['4', '48', '7548']]