使用“regex”的 Python 模糊字符串搜索

Python fuzzy string search with `regex`

提问人:RolfBly 提问时间:11/15/2023 最后编辑:RolfBly 更新时间:11/16/2023 访问量:63

问:

试图理解与正则表达式的模糊模式匹配。我想要什么:我有一个字符串,我想在其他字符串中找到相同或相似的字符串,也许是更大的字符串。(数据库记录中的某个字段是否出现在该数据库记录中的任何其他字段中,可能作为模糊子字符串?

下面是一个示例。注释指示字符位置。

import regex
to_search = "1990 /"
            #123456
            # ^^ ^
search_in = "V CAD-0000:0000[01] ISS 23/10/91"
            #12345678901234567890123456789012
            #                           ^^ ^
m = regex.search(f'({to_search}){{e<4}}', search_in, regex.BESTMATCH)

结果:

>>> m
<regex.Match object; span=(27, 30), match='10/', fuzzy_counts=(0, 0, 3)>
>>> m.fuzzy_changes
([], [], [28, 29, 31])    

没有插入,没有替换,在第 28、29 和 31 位删除了 3 个。“插入、替换、删除”的顺序很重要,它取自此处

问题:如何用正常的人类语言来解释这一点?它了什么(我认为):

“如果你删除其中的位置 28、29 和 31,你的子字符串中有一个匹配项。”10/search_in

我可能弄错了。这是真的':

“如果你删除位置 5、3 和 2,按这个顺序,在 中,你在子字符串处有一个完全匹配,耶!”to_search10/search_in

幸运的是,我找到了一位大师!所以我做到了

>>> import orc
>>> m = regex.search(f'({to_search}){{e<4}}', search_in, regex.BESTMATCH)
>>> m
<regex.Match object; span=(27, 30), match='10/', fuzzy_counts=(0, 0, 3)>
>>> near_match = orc.NearMatch.from_regex(m, to_search)
>>> print(near_match)
10/
 I
190/
  I
1990/
    I
1990 /

嗯。。。所以 的顺序 ,实际上是某物、某物、插入吗fuzzy_counts

如果有人能对此有所了解,我将不胜感激。

python 正则表达式 模糊搜索

评论

2赞 sln 11/15/2023
没有人理解 Python 的模糊 i、d、s、e。尝试这样做的正则表达式源代码必须是原始的才能执行,并且实际上只适用于语言“单词”级别。整个概念有点模糊。
0赞 RolfBly 11/15/2023
@sin 多么令人放心。谢谢!

答:

1赞 nithinks 11/16/2023 #1

你很接近。但根据你在帖子中提到的文档,这就是这里发生的事情。

import regex
to_search = "1990 /"
            #123456
            # ^^ ^
search_in = "V CAD-0000:0000[01] ISS 23/10/91"
            #12345678901234567890123456789012
            #                           ^^ ^
m = regex.search(f'({to_search}){{e<4}}', search_in, regex.BESTMATCH)
m

输出:

<regex.Match object; span=(27, 30), match='10/', fuzzy_counts=(0, 0, 3)>

m.fuzzy_changes

输出:

([], [], [28, 29, 31])


解释

让我们一步一步地分解它:

背景:

您正在较长的文本“V CAD-0000:0000[01] ISS 23/10/91”中搜索确切的序列“1990 /”。

研究结果:

  • 找到匹配项:搜索在较长的文本中发现了类似的序列“10/”。
  • 位置:这个“10/”序列是从较长文本的第 27 到 30 个位置开始发现的。

分析:

为了获得精确匹配,我们应该有更长的字符串,如下所示

V CAD-0000:0000[01] ISS 23/1990 /91

但是,对该字符串进行了一些更改以获取实际字符串。

变化:

  1. 删除:
    • 位置:删除了假定原始序列中的位置 28、29 和 31。V CAD-0000:0000[01] ISS 23/1990 /91
    • 结果字符串:删除这些后,假定的原始序列变成了实际序列。V CAD-0000:0000[01] ISS 23/10/91

评论

0赞 RolfBly 11/17/2023
非常感谢您的解释。我现在更好地理解了结果,但我仍然很困惑为什么它以“为了获得精确匹配,我们应该将更长的字符串作为 X”开头。人们会期望从到子字符串的编辑距离。从匹配的假设子字符串到 获得编辑距离。我可以看到它归结为同一件事。我只是对这种方法很感兴趣。to_searchsearch_insearch_into_searchsearch_in