匹配差异不大的单词

时间:2018-07-11 08:07:58

标签: regex linux bash terminal similarity

我想知道是否有任何工具可以将几乎匹配为bash终端。

在名为 list.txt 的以下文件中,每行包含1个单词:

ban
1ban
12ban
12ban3

很容易找到包含“禁令”的字词

grep -E "*ban*" list.txt

问题:

如何真正匹配具有x个字母差异的单词? 对于搜索字词“ ban”,我希望X = 1匹配“ 1ba​​n”。

关于距离的概念,我想最大化: X删除 或X替代 或X个插入

任何工具,但最好在bash终端上以命令行方式调用。

注意:Levenshtein距离会将2个字母的插入算作1个差异。这不是我想要的。

2 个答案:

答案 0 :(得分:1)

您可以使用支持模糊匹配的Python PyPi regex类。

由于您实际上想匹配具有最大 X 差异(1个删除或1个替换或1个删除)的单词,因此您可以创建类似

的Python脚本
#!/usr/bin/env python3
import regex, io, sys

def main(argv):
        if len(argv) < 3:
                # print("USAGE: fuzzy_search -searchword -xdiff -file")
                exit(-1)
        search=argv[0]
        xdiff=argv[1]
        file=argv[2]
        # print("Searching for {} in {} with {} differences...".format(search, file, xdiff))
        with open(file, "r") as f:
                contents = f.read()
                print(regex.findall(r"\b(?:{0}){{s<={1},i<={1},d<={1}}}\b".format(regex.escape(search), xdiff), contents))

if __name__ == "__main__":
        main(sys.argv[1:])

在这里,{s<=1,i<=1,d<=1}表示我们允许搜索1或0个替换(s<=1,1或0个插入(i<=1)或1或0个删除({{1 }}。

d<=1单词边界,由于采用了这种结构,因此只匹配整个单词(\b中没有cat会被匹配)。

另存为vacation

然后,您可以将其命名为

fuzzy_search.py

其中python3 fuzzy_search.py "ban" 1 file 是执行模糊搜索的词,而"ban"是差异的上限。

我得到的结果是

1

您可以将输出格式更改为仅行:

['ban', '1ban']

然后,结果是

print("\n".join(regex.findall(r"\b(?:{0}){{s<={1},i<={1},d<={1}}}\b".format(regex.escape(search), xdiff), contents)))

答案 1 :(得分:0)

您可以通过使用python检查每个字符来检查如下所示的差异

def is_diff(str1, str2):
    diff = False
    for char1, char2 in zip(str1, str2):
        if char1 != char2:
            if diff:
                return False
            else:
                diff = True
    return diff
with open('list.txt') as f:
    data = f.readlines()

for line in data:
    print is_diff('ban', line)