2012-03-31 13 views
7

Chciałbym, aby wyrażenie regularne pasowało do sekwencji bajtów, gdy ciąg '02 d0 'nie występuje w określonej pozycji w łańcuchu. Pozycja, w której ten ciąg dwóch bajtów nie może wystąpić, to pozycje bajtów 6 i 7 rozpoczynające się od 0. bajtu po prawej stronie.Negatywne spojrzenie na przyszłość python regex

To co używam do testowania:

#!/usr/bin/python 
import re 

p0 = re.compile('^24 [\da-f]{2} 03 (01|03) [\da-f]{2} [\da-f]{2} [\da-f]{2} (([^0])| (0[^2])|(02 [^d])|(02 d[^0])) 01 c2 [\da-f]{2} [\da-f]{2} [\da-f]{2} 23') 
p1 = re.compile('^24 [\da-f]{2} 03 (01|03) [\da-f]{2} [\da-f]{2} [\da-f]{2} (([^0])|(0[^2])|(02 [^d])|(02 d[^0])) 01') 
p2 = re.compile('^24 [\da-f]{2} 03 (01|03) [\da-f]{2} [\da-f]{2} [\da-f]{2} (([^0])|(0[^2])|(02 [^d])|(02 d[^0]))') 
p3 = re.compile('^24 [\da-f]{2} 03 (01|03) [\da-f]{2} [\da-f]{2} [\da-f]{2} (?!02 d0) 01') 
p4 = re.compile('^24 [\da-f]{2} 03 (01|03) [\da-f]{2} [\da-f]{2} [\da-f]{2} (?!02 d0)') 

yes = '24 0f 03 01 42 ff 00 04 a2 01 c2 00 c5 e5 23' 
no = '24 0f 03 01 42 ff 00 02 d0 01 c2 00 c5 e5 23' 

print p0.match(yes) # fail 
print p0.match(no) # fail 
print '\n' 
print p1.match(yes) # fail 
print p1.match(no) # fail 
print '\n' 
print p2.match(yes) # PASS 
print p2.match(no) # fail 
print '\n' 
print p3.match(yes) # fail 
print p3.match(no) # fail 
print '\n' 
print p4.match(yes) # PASS 
print p4.match(no) # fail 

Spojrzałem na this example, ale ta metoda jest mniej restrykcyjne niż muszę. Czy ktoś mógłby wyjaśnić, dlaczego mogę poprawnie dopasować tylko wtedy, gdy negatywne spojrzenie jest na końcu ciągu? Co muszę zrobić, aby dopasować, gdy "02 d0" nie występuje w tej konkretnej pozycji bitu?

+1

Czy jestem jedynym, który uważa, że ​​'[0-9a-f]' jest bardziej czytelny niż '[\ da-f]'? – ThiefMaster

+0

Masz na myśli "pozycje 7 i 8", prawda? – Qtax

Odpowiedz

11

Przegięcia są "zerowej szerokości", co oznacza, że ​​nie zużywają żadnych znaków. Na przykład, te dwa wyrażenia nie pasuje:

  1. (?=foo)bar
  2. (?!foo)foo

Aby upewnić się liczba nie jest jakiś specyficzny numer, można użyć:

(?!42)\d\d # will match two digits that are not 42 

W Twój przypadek może wyglądać następująco:

(?!02)[\da-f]{2} (?!0d)[\da-f]{2} 

czyli

(?!02 d0)[\da-f]{2} [\da-f]{2} 
+0

To było bardzo dobre wytłumaczenie. Wielkie dzięki! – Michael

+0

Dlaczego użyto [\ da-f]? – umayneverknow

+0

@umayneverknow '[\ da-f]' dopasowuje cyfrę heksadecymalną. Równoważnie można użyć "[0-9a-f]". – frederick99