Python正则表达式部分匹配或“hitEnd”

2 投票
1 回答
1039 浏览
提问于 2025-04-18 15:45

我正在写一个扫描器,目的是把一个任意字符串和一系列正则表达式规则进行匹配。如果我能模拟Java中的“hitEnd”功能,那就太好了,这样我不仅能知道正则表达式没有匹配成功,还能知道它绝对匹配不了;也就是说,当正则表达式匹配器在输入的末尾时,它还没有决定拒绝匹配,这表明如果输入更长一些,可能会符合规则。

举个例子,我可能是在匹配HTML标签,用来加粗一个句子,比如“< b >”。所以我编写了我的规则:

bold_html_rule = re.compile("<b>")

然后我进行了一些测试:

good_match = bold_html_rule.match("<b>")
uncertain_match = bold_html_rule.match("<")
bad_match = bold_html_rule.match("goat")

我怎么才能区分“坏”的匹配,也就是goat永远无法通过更多输入变得有效的情况,以及那种模棱两可的匹配,虽然现在还不是匹配,但将来可能会是。

尝试

  1. 很明显,在上面的情况下,没有办法区分,因为不确定的尝试和坏的尝试都会返回“None”。如果我把所有规则都包裹在“(RULE)?”中,那么任何输入都会返回匹配,因为至少空字符串是所有字符串的子字符串。然而,当我尝试使用group方法或endPos字段查看正则表达式在拒绝我的字符串之前进展到了什么程度时,它总是返回字符串的长度。

Python的正则表达式包是不是做了很多额外的工作,即使在第一个字符就已经是无效匹配的情况下,也会遍历整个字符串?我能理解如果我使用search,它会检查这个序列是否在输入的任何地方,但对于match来说,这样做似乎很奇怪。

我发现之前有人在其他地方问过类似的问题,比如这个链接: https://mail.python.org/pipermail/python-list/2012-April/622358.html 但他并没有得到真正的回应。

我查看了正则表达式包本身,但没能弄清楚它的行为;我能扩展这个包来得到我想要的结果吗?或者说,这根本就是处理我任务的错误方法(我过去用这种策略构建过有效的Java扫描器)

1 个回答

0

试试这个方法。虽然感觉有点像是变通的办法,但至少能达到你想要的效果。不过,我对这个 PrepareCompileString 函数有点担心。它应该能处理所有的 转义字符,但对 通配符 就无能为力了。

import re

#Grouping every single character
def PrepareCompileString(regexString):
    newstring = ''
    escapeFlag = False
    for char in regexString:
        if escapeFlag:
            char = escapeString+char
            escapeFlag = False
            escapeString = ''
        if char == '\\':
            escapeFlag = True
            escapeString = char
        if not escapeFlag:
            newstring += '({})?'.format(char)
    return newstring

def CheckMatch(match):

    # counting the number of non matched groups
    count = match.groups().count(None)

    # If all groups matched - good match 
    # all groups did not match - bad match
    # few groups matched - uncertain match

    if count == 0:
        print('Good Match:', match.string)
    elif count < len(match.groups()):
        print('Uncertain Match:', match.string)
    elif count == len(match.groups()):
        print('Bad Match:', match.string)

regexString = '<b>'
bold_html_rule = re.compile(PrepareCompileString(regexString))

good_match = bold_html_rule.match("<b>")
uncertain_match = bold_html_rule.match("<")
bad_match = bold_html_rule.match("goat")

for match in [good_match, uncertain_match, bad_match]:
    CheckMatch(match)

我得到了这个结果:

Good Match: <b>
Uncertain Match: <
Bad Match: goat

撰写回答