负向先行断言 Python 正则表达式。

27
我想使用正则表达式匹配一段字节序列,但是当“02 d0”不出现在字符串的特定位置时。这个两个字节串不能出现在从右边开始数第6和第7个字节的位置上。以下是我用来测试的代码:
#!/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

我看了这个示例,但那种方法比我需要的限制要少。请问为什么只有当否定的前瞻在字符串的末尾时才能正确匹配?如果'02 d0'不出现在这个特定的位位置,我需要做什么才能匹配?


3
我是不是唯一一个认为[0-9a-f][\da-f]更易读的人? - ThiefMaster
你是指"第七和八个位置",对吗? - Qtax
1个回答

50

顾虑符号是“零宽度”的,这表示它们不会消耗任何字符。例如,以下两个表达式永远不会匹配:

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

要确保一个数字不是某个特定的数字,您可以使用:

(?!42)\d\d # will match two digits that are not 42
在你的情况下,它可能看起来像这样:
(?!02)[\da-f]{2} (?!0d)[\da-f]{2}
或:
(?!02 d0)[\da-f]{2} [\da-f]{2}

1
为什么要使用 [\da-f]? - umayneverknow
3
[\da-f] 可以匹配一个十六进制数字。等价地,可以使用 [0-9a-f] 来表示。 - frederick99

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接