2010-09-02 203 views
3

有没有一种方法可以确定正则表达式是否只匹配固定长度字符串? 我的想法是扫描*,+和?然后,需要一些智能逻辑来寻找其中m!= n的{m,n}。 没有必要采取|运营商考虑在内。
小例子:^ \ d {4}是固定长度的;^\ d {4,5}或^ \ d +是可变长度确定正则表达式是否只匹配固定长度字符串

我正在使用PCRE。

谢谢。

保罗Praet

+2

编程? – kennytm 2010-09-02 13:32:59

+0

用另一个正则表达式? :) – Ani 2010-09-02 13:39:28

+0

它肯定有必要考虑'|'。毕竟,正则表达式'/ ab | c /'的固定长度是多少? – 2010-09-02 13:45:03

回答

4

嗯,你可以利用一个事实,即Python的正则表达式引擎只允许在后向断言固定长度的正则表达式:

import re 
regexes = [r".x{2}(abc|def)", # fixed 
      r"a|bc",   # variable/finite 
      r"(.)\1",   # fixed 
      r".{0,3}",   # variable/finite 
      r".*"]    # variable/infinite 

for regex in regexes: 
    try: 
     r = re.compile("(?<=" + regex + ")") 
    except: 
     print("Not fixed length: {}".format(regex)) 
    else: 
     print("Fixed length: {}".format(regex)) 

将输出

Fixed length: .x{2}(abc|def) 
Not fixed length: a|bc 
Fixed length: (.)\1 
Not fixed length: .{0,3} 
Not fixed length: .* 

我假设正则表达式本身是有效的。

现在,Python如何知道正则表达式是否为固定长度?只要阅读源代码 - 在sre_parse.py中,有一种称为getwidth()的方法,返回由最低和最高可能长度组成的元组,并且如果这些元素在向后追踪断言中不相等,则re.compile()将引发错误。该方法getwidth()遍历该正则表达式递归:

def getwidth(self): 
    # determine the width (min, max) for this subpattern 
    if self.width: 
     return self.width 
    lo = hi = 0 
    UNITCODES = (ANY, RANGE, IN, LITERAL, NOT_LITERAL, CATEGORY) 
    REPEATCODES = (MIN_REPEAT, MAX_REPEAT) 
    for op, av in self.data: 
     if op is BRANCH: 
      i = sys.maxsize 
      j = 0 
      for av in av[1]: 
       l, h = av.getwidth() 
       i = min(i, l) 
       j = max(j, h) 
      lo = lo + i 
      hi = hi + j 
     elif op is CALL: 
      i, j = av.getwidth() 
      lo = lo + i 
      hi = hi + j 
     elif op is SUBPATTERN: 
      i, j = av[1].getwidth() 
      lo = lo + i 
      hi = hi + j 
     elif op in REPEATCODES: 
      i, j = av[2].getwidth() 
      lo = lo + int(i) * av[0] 
      hi = hi + int(j) * av[1] 
     elif op in UNITCODES: 
      lo = lo + 1 
      hi = hi + 1 
     elif op == SUCCESS: 
      break 
    self.width = int(min(lo, sys.maxsize)), int(min(hi, sys.maxsize)) 
    return self.width 
+0

我在C编码,使用PCRE库......无论如何:-) – 2010-09-02 15:53:28

0

根据regular-expressions.info,所述PCRE发动机仅支持固定长度的正则表达式和交替内部lookbehinds。

所以,如果你有一个有效的正则表达式,围绕它与(?<=)并看看它是否仍然编译。然后你知道它是固定大小的还是固定大小的正则表达式的交替。

我不确定类似a(b|cd)e的东西 - 这绝对不是固定大小的,但它仍然可以编译。你需要尝试一下(我没有安装C/PCRE)。

1

只是为了好玩。

假设我们反对只测试正则表达式支持+*?{m,n}{n}[...](除了一些奇怪的语法像[]][^]])。那么正则表达式是仅当它跟随语法固定长度:

REGEX  -> ELEMENT * 
ELEMENT -> CHARACTER ('{' (\d+) (',' \1)? '}')? 
CHARACTER -> [^+*?\\\[] | '\\' . | '[' ('\\' . | [^\\\]])+ ']' 

可以在PCRE被重写为:

^(?:(?:[^+*?\\\[{]|\\.|\[(?:\\.|[^\\\]])+\])(?:\{(\d+)(?:,\1)?\})?)*$ 
+1

我承认我不知道你的意思;-) 你的意思是正则表达式本身应该匹配上面的表达式? – 2010-09-02 19:57:08