在Python中匹配2个正则表达式
可以在Python中匹配2个正则表达式吗 例如,我有一个用例,其中我需要比较如下两个表达式:在Python中匹配2个正则表达式,python,regex,Python,Regex,可以在Python中匹配2个正则表达式吗 例如,我有一个用例,其中我需要比较如下两个表达式: re.match('google\.com\/maps', 'google\.com\/maps2', re.IGNORECASE) 我希望得到一个RE对象 但是很明显,Python期望字符串作为第二个参数。 有没有办法做到这一点,或者这是正则表达式匹配工作方式的一个限制 背景:我有一个与字符串匹配的正则表达式列表[r1、r2、r3,…],我需要找出哪个表达式与给定字符串最匹配。我认为我可以通过:
re.match('google\.com\/maps', 'google\.com\/maps2', re.IGNORECASE)
我希望得到一个RE对象
但是很明显,Python期望字符串作为第二个参数。
有没有办法做到这一点,或者这是正则表达式匹配工作方式的一个限制
背景:我有一个与字符串匹配的正则表达式列表[r1、r2、r3,…],我需要找出哪个表达式与给定字符串最匹配。我认为我可以通过:
(1) 将r1与r2匹配。
(2) 然后将r2与r1匹配。
如果双方都匹配,我们就“平局”。如果只有(1)个匹配有效,则r1比r2更匹配,反之亦然。
我会在整个列表上循环(1)和(2)
我承认这有点牵强附会(主要是因为我的描述可能不连贯),但如果有人能给我一些关于如何实现这一点的见解,我会非常感激。谢谢 我认为这是不可能的 另一种方法是尝试计算正则表达式也匹配的长度为n的字符串数。匹配长度为15个字符的100000000个字符串的正则表达式比仅匹配长度为15个字符的10个字符串的正则表达式更不特定 当然,除非正则表达式很简单,否则计算可能的匹配数并非易事。选项1: 由于用户提供正则表达式,可能会要求他们也提交一些测试字符串,他们认为这些字符串可以说明正则表达式的特殊性。(即,显示他们的正则表达式比竞争对手的正则表达式更具体)收集用户提交的所有测试字符串,然后根据完整的测试字符串集测试所有正则表达式 为了设计一个好的正则表达式,作者必须考虑哪些字符串匹配,哪些字符串不匹配,所以他们应该很容易提供好的测试字符串
备选案文2: 您可以尝试蒙特卡罗方法:从两个正则表达式都匹配的字符串开始,编写一个生成器,生成该字符串的突变(排列字符、添加/删除字符等)。如果两个正则表达式对每个突变都匹配或不匹配相同的方式,则正则表达式“可能匹配”。如果一个匹配另一个不匹配的突变,反之亦然,那么它们“绝对匹配” 但是,如果一个匹配一个严格的突变超集,那么它“可能比另一个更不具体” 大量突变后的结论可能并不总是正确的,但可能是合理的
备选案文3:
使用或pyParsing生成与每个正则表达式匹配的字符串。这只适用于使用有限的正则表达式语法子集的正则表达式。我认为您可以通过查看匹配结果和最长结果来实现
>>> m = re.match(r'google\.com\/maps','google.com/maps/hello')
>>> len(m.group(0))
15
>>> m = re.match(r'google\.com\/maps2','google.com/maps/hello')
>>> print (m)
None
>>> m = re.match(r'google\.com\/maps','google.com/maps2/hello')
>>> len(m.group(0))
15
>>> m = re.match(r'google\.com\/maps2','google.com/maps2/hello')
>>> len(m.group(0))
16
上面re.match()
的第二项是一个字符串——这就是它不起作用的原因:正则表达式说要匹配google后面的句点,但它找到了一个反斜杠。您需要做的是将用作正则表达式的正则表达式中的反斜杠加倍:
def compare_regexes(regex1, regex2):
"""returns regex2 if regex1 is 'smaller' than regex2
returns regex1 if they are the same
returns regex1 if regex1 is 'bigger' than regex2
otherwise returns None"""
regex1_mod = regex1.replace('\\', '\\\\')
regex2_mod = regex2.replace('\\', '\\\\')
if regex1 == regex2:
return regex1
if re.match(regex1_mod, regex2):
return regex2
if re.match(regex2_mod, regex1):
return regex1
您可以将回报更改为最适合您需要的任何回报。哦,请确保您使用的是带有re的原始字符串r'像这样,例如'
可以在Python中匹配2个正则表达式吗
这当然是可能的。使用由|
连接的插入式匹配组进行更改。如果将括号内的匹配组按最特定的正则表达式排列为最不特定的正则表达式,则从m.groups()
返回的元组中的秩将显示匹配的具体程度。您还可以使用命名组来命名匹配的具体程度,例如对于非常特定的匹配,可以使用s10
;对于不太特定的匹配,可以使用s0
>>> s1='google.com/maps2text'
>>> s2='I forgot my goggles at the house'
>>> s3='blah blah blah'
>>> m1=re.match(r'(^google\.com\/maps\dtext$)|(.*go[a-z]+)',s1)
>>> m2=re.match(r'(^google\.com\/maps\dtext$)|(.*go[a-z]+)',s2)
>>> m1.groups()
('google.com/maps2text', None)
>>> m2.groups()
(None, 'I forgot my goggles')
>>> patt=re.compile(r'(?P<s10>^google\.com\/maps\dtext$)|
... (?P<s5>.*go[a-z]+)|(?P<s0>[a-z]+)')
>>> m3=patt.match(s3)
>>> m3.groups()
(None, None, 'blah')
>>> m3.groupdict()
{'s10': None, 's0': 'blah', 's5': None}
>>s1='google.com/maps2text'
>>>我把护目镜忘在家门口了
>>>s3=‘废话废话’
>>>m1=re.match(r'(^google\.com\/maps\dtext$)|(.*go[a-z]+),s1)
>>>m2=re.match(r'(^google\.com\/maps\dtext$)|(.*go[a-z]+)),s2)
>>>m1.组()
('google.com/maps2text',无)
>>>m2.组()
(没有,“我忘了带护目镜了”)
>>>patt=re.compile(r'(?P^google\.com\/maps\dtext$)|
…(?P.*go[a-z]+)|(?P[a-z]+))
>>>m3=零件匹配(s3)
>>>m3.团体()
(没有,没有,'废话')
>>>m3.groupdict()
{'s10':无,'s0':'blah','s5':无}
如果您事先不知道哪个正则表达式更具体,这是一个更难解决的问题。您想看看针对文件系统名称的正则表达式匹配的安全性 除了关于
re.match
的语法说明之外,我认为我理解您正在努力获取两个或更多未知(用户输入)正则表达式,并对字符串中哪一个匹配更“具体”进行分类
回想一下,Python正则表达式实际上是一种计算机程序。大多数现代表单,包括Python的正则表达式,都基于Perl。Perl的正则表达式具有递归、回溯和其他形式,这些形式不需要进行简单的检查。事实上,一个流氓正则表达式可以作为一种
要在您自己的计算机上查看此信息,请尝试:
>>> re.match(r'^(a+)+$','a'*24+'!')
在我的电脑上大约需要1秒钟。现在将'a'*24
中的24
增加一个稍大的数字,比如说28
。这需要更长的时间。请尝试48
。。。您现在可能需要按CTRL+C组合键。时间随着a的数量的增加而增加,事实上,是指数的
关于这个问题,你可以在上一篇精彩的文章中读到更多。罗斯·考克斯是2006年建造的护目镜工程师。正如Cox观察到的,考虑将正则表达式>代码> a”* 33×+“a×33 < /代码>与“代码> >”a×99 < /代码>,用AWK和Perl(或Python或PCRE或java或PHP……)AWK在200微秒中匹配,但Perl由于指数反跟踪需要1015年。
所以结论是
>>> re.match(r'^(a+)+$','a'*24+'!')
import re
def ld(a,b):
"Calculates the Levenshtein distance between a and b."
n, m = len(a), len(b)
if n > m:
# Make sure n <= m, to use O(min(n,m)) space
a,b = b,a
n,m = m,n
current = range(n+1)
for i in range(1,m+1):
previous, current = current, [i]+[0]*n
for j in range(1,n+1):
add, delete = previous[j]+1, current[j-1]+1
change = previous[j-1]
if a[j-1] != b[i-1]:
change = change + 1
current[j] = min(add, delete, change)
return current[n]
s='Mary had a little lamb'
d={}
regs=[r'.*', r'Mary', r'lamb', r'little lamb', r'.*little lamb',r'\b\w+mb',
r'Mary.*little lamb',r'.*[lL]ittle [Ll]amb',r'\blittle\b',s,r'little']
for reg in regs:
m=re.search(reg,s)
if m:
print "'%s' matches '%s' with sub group '%s'" % (reg, s, m.group(0))
ld1=ld(reg,m.group(0))
ld2=ld(m.group(0),s)
score=max(ld1,ld2)
print " %i edits regex->match(0), %i edits match(0)->s" % (ld1,ld2)
print " score: ", score
d[reg]=score
print
else:
print "'%s' does not match '%s'" % (reg, s)
print " ===== %s ===== === %s ===" % ('RegEx'.center(10),'Score'.center(10))
for key, value in sorted(d.iteritems(), key=lambda (k,v): (v,k)):
print " %22s %5s" % (key, value)
===== RegEx ===== === Score ===
Mary had a little lamb 0
Mary.*little lamb 7
.*little lamb 11
little lamb 11
.*[lL]ittle [Ll]amb 15
\blittle\b 16
little 16
Mary 18
\b\w+mb 18
lamb 18
.* 22
import re
import sre_parse
def ld(a,b):
"Calculates the Levenshtein distance between a and b."
n, m = len(a), len(b)
if n > m:
# Make sure n <= m, to use O(min(n,m)) space
a,b = b,a
n,m = m,n
current = range(n+1)
for i in range(1,m+1):
previous, current = current, [i]+[0]*n
for j in range(1,n+1):
add, delete = previous[j]+1, current[j-1]+1
change = previous[j-1]
if a[j-1] != b[i-1]:
change = change + 1
current[j] = min(add, delete, change)
return current[n]
s='Mary had a little lamb'
d={}
regs=[r'.*', r'Mary', r'lamb', r'little lamb', r'.*little lamb',r'\b\w+mb',
r'Mary.*little lamb',r'.*[lL]ittle [Ll]amb',r'\blittle\b',s,r'little',
r'^.*lamb',r'.*.*.*b',r'.*?.*',r'.*\b[lL]ittle\b \b[Ll]amb',
r'.*\blittle\b \blamb$','^'+s+'$']
for reg in regs:
m=re.search(reg,s)
if m:
ld1=ld(reg,m.group(0))
ld2=ld(m.group(0),s)
score=max(ld1,ld2)
for t, v in sre_parse.parse(reg):
if t=='at': # anchor...
if v=='at_beginning' or 'at_end':
score-=1 # ^ or $, adj 1 edit
if v=='at_boundary': # all other anchors are 2 char
score-=2
d[reg]=score
else:
print "'%s' does not match '%s'" % (reg, s)
print
print " ===== %s ===== === %s ===" % ('RegEx'.center(15),'Score'.center(10))
for key, value in sorted(d.iteritems(), key=lambda (k,v): (v,k)):
print " %27s %5s" % (key, value)
===== RegEx ===== === Score ===
Mary had a little lamb 0
^Mary had a little lamb$ 0
.*\blittle\b \blamb$ 6
Mary.*little lamb 7
.*\b[lL]ittle\b \b[Ll]amb 10
\blittle\b 10
.*little lamb 11
little lamb 11
.*[lL]ittle [Ll]amb 15
\b\w+mb 15
little 16
^.*lamb 17
Mary 18
lamb 18
.*.*.*b 21
.* 22
.*?.* 22