我正在尝试编写一个实现简单正则表达式匹配算法的函数。特殊字符“*”和“?”应分别代表1和n> = 0自由度。例如字符串
y="abc" and x="a*c",
y="abc" and x="a?c",
y="abddddzfjc" and x="a?" or x="a?c"
应该返回True,而字符串
y="abcd" and x="a*d",
y="abcdef" and x="a?d*"
应该返回False。
我的方法是在循环中运行并缩短字符串,因为每个后续匹配都被识别,这对于相同的匹配或单个*与字母字符匹配工作正常,但我对如何为边缘情况执行此操作感到困惑像最后一个例子。处理“?”的情况有n个自由度,我在右边的字符串中向前循环以找到下一个字母字符,然后尝试在左边的字符串中查找该字符,从右到左查看。我相信有一种更优雅的方式(也许有发电机?!)。
def match_func(x,y):
x, y = list(x), list(y)
if len(x)==len(y)==1:
if x[0] == y[0] or bool((set(x)|set(y)) & {"?","*"})
return True
elif len(x)>0 and len(y)==0:
return False
else:
for ix, char in enumerate(x):
if char==y[ix] or char=="*":
return match_func(x[ix+1:],y[ix+1:])
else:
if char=="?"
if ix==len(x)=1: return True
##check if the next letter in x has an eventual match in y
peek = ix+1
next_char = x[peek]
while peek<len(x)-1:
next_char = x[peek]
if next_char.isalpha():
break
else: peek+=1
if peek == len(x)-1:
return True
ys = ''.join(y)
next_char_ix = ys[ix].rfind(next_char)
##search y for next possible match?
if next_char_ix!=-1:
return match_func(x[peek:], y[next_char_ix:])
else:
return False
else:
return False
return True
答案 0 :(得分:0)
首先决定是否将匹配算法设为 minimal 或 maximal 搜索。这意味着,如果您的模式是a
,并且您的主题字符串是aa
,那么匹配是在第一个还是第二个位置发生的?当你陈述问题时,任何一种选择似乎都是可以接受的。
做出这个选择之后,你将会清楚地知道如何遍历字符串 - 尽可能向右移动然后向后工作直到你匹配或失败;或者从左边开始,每次尝试后回溯。
我建议使用递归实现。在每个位置,评估您是否有匹配。如果是这样,请使您的递归调用在模式和主题字符串中向前推进适当的数量。如果没有,请放弃。如果模式的第一个字符不匹配,则仅前进主题字符串(根据您的最小/最大选择),然后重试。
棘手的部分是,你必须考虑模式中的可变长度标记作为可能的匹配,即使相同的字符也匹配该通配符后面的文字字符。这使你进入深度优先搜索的领域。评估像a?a?a?a
这样的主题字符串上的aaaabaaaa
等模式会很有趣,如果你把它推得太远,可能需要数年才能完成。
你的教授很好地选择了正则表达式运算符,让你做出有意义的深度分配,而没有编写一个完整的解析器和词法分析器,以使事情有效。
祝你好运!