Perl - 如何匹配不完全相同的字符串?

3

我有一组字符串,想要在文件中查找。如果我的列表中的字符串与文件中的完全匹配,那么这将是相当简单的。不幸的是,名称可能存在拼写错误和变体。以下是其中一些字符串的示例:

List          File
B-Arrestin    Beta-Arrestin
Becn-1        BECN 1
CRM-E4        CRME4

请注意,尽管这些字符串不同,但每对字符串都应计算为匹配。 我知道我可以将每种变化分类并编写单独的正则表达式来识别匹配,但这很麻烦,我手动查找匹配可能更好。我认为解决我的问题的最佳方案应该是一种表达式,它说:

“完全匹配此字符串,但仍将其视为匹配,如果存在X个不匹配的字符”

是否存在这样的东西?是否有其他方法匹配不完全相同但接近的字符串?


去除非字母数字字符并进行不区分大小写的比较可用于第二和第三行。当然,如果您的文件中也有 B-Ecn-1,那么它也会被(我认为是错误地)标记为匹配项。您能否列出前缀及其缩写的列表以涵盖第一种情况,例如 Beta -> B? - ThisSuitIsBlackNot
这种方法的问题在于我不知道存在哪些类型的变化。然而,我有信心可以通过肉眼立即发现错误匹配,这就是为什么我希望有一种方法来进行准确度不完全匹配的字符串匹配。 - Slavatron
2个回答

5
根据200_success指出的,您可以使用Text::Fuzzy进行模糊匹配,它计算文本的Levenshtein距离。您需要调整允许的最大Levenshtein距离,但如果进行不区分大小写的比较,则示例数据中的最大距离为3:
use strict;
use warnings;
use 5.010;

use Text::Fuzzy;

my $max_dist = 3;

while (<DATA>) {
    chomp;
    my ($string1, $string2) = split ' ', $_, 2;

    my $tf = Text::Fuzzy->new(lc $string1);
    say "'$string1' matches '$string2'" if $tf->distance(lc $string2) <= $max_dist;
}

__DATA__
B-Arrestin    Beta-Arrestin
Becn-1        BECN 1
CRM-E4        CRME4

输出:

'B-Arrestin' matches 'Beta-Arrestin'
'Becn-1' matches 'BECN 1'
'CRM-E4' matches 'CRME4'

3

2
通常情况下,答案是“CPAN有一个相应的模块”。 - Degustaf
根据 OP 的示例数据,“String::Approx” 可能不是最好的工具。从文档中可以看到:“String::Approx 不适用于比较长度不同的字符串...”。 - ThisSuitIsBlackNot

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接