如何按功能比较正则表达式对象?等价正则需判定相等
功能等价的正则表达式对象比较方法
你提到的这两个正则表达式确实功能完全一致——一个用了VERBOSE模式(re.X)添加注释和空格提升可读性,另一个是紧凑的简洁写法:
import re a = re.compile(r"""\d + # the integral part \. # the decimal point \d * # some fractional digits""", re.X) b = re.compile(r"\d+\.\d*")
但直接执行a == b会返回False,因为re.compile生成的是独立的正则对象,哪怕匹配逻辑完全相同,实例本身也是不同的。要按功能比较它们,让a == b返回True,可以试试这两种方法:
方法1:标准化正则模式后比较
VERBOSE模式下的空格和注释不会影响实际匹配逻辑,所以我们可以把a的模式转换成普通模式下的等价字符串,再和b的模式对比:
def normalize_regex(pattern, flags): if flags & re.X: # 移除VERBOSE模式下的注释和无关空格 cleaned_lines = [] for line in pattern.splitlines(): # 截断#后的注释内容,再去掉首尾空格 cleaned_line = line.split('#')[0].strip() if cleaned_line: cleaned_lines.append(cleaned_line) return ''.join(cleaned_lines) return pattern # 对两个正则的模式做标准化处理后比较 normalized_a = normalize_regex(a.pattern, a.flags) normalized_b = normalize_regex(b.pattern, b.flags) print(normalized_a == normalized_b) # 输出True
如果想让a == b直接返回True,可以自定义一个包装类,重写__eq__方法来实现功能层面的相等判断:
class RegexWrapper: def __init__(self, pattern, flags=0): self.re_obj = re.compile(pattern, flags) self.normalized_pattern = normalize_regex(pattern, flags) self.flags = flags def __eq__(self, other): if not isinstance(other, RegexWrapper): return False # 对比标准化后的模式(忽略不影响匹配的格式差异) return self.normalized_pattern == other.normalized_pattern # 使用包装类创建正则对象 a_wrap = RegexWrapper(r"""\d + # the integral part \. # the decimal point \d * # some fractional digits""", re.X) b_wrap = RegexWrapper(r"\d+\.\d*") print(a_wrap == b_wrap) # 输出True
方法2:通过匹配行为验证等价性
更直观可靠的方式是用测试用例验证两个正则的匹配结果完全一致:
test_cases = [ # 应该匹配的场景 "123.45", "0.", "123.", "987654.123", # 不应该匹配的场景 "abc", "123", ".45", "123..45", " 123.45" ] def is_regex_equivalent(re1, re2, test_cases): for case in test_cases: match_result1 = bool(re1.match(case)) match_result2 = bool(re2.match(case)) if match_result1 != match_result2: return False return True print(is_regex_equivalent(a, b, test_cases)) # 输出True
这种方法能直接验证正则的功能等价性,尤其适合复杂正则的对比场景。
内容的提问来源于stack exchange,提问作者Chertkov Pavel
相关产品推荐
相关产品推荐

