我正在搜索“卡扎菲”这个词,这个词有很多种拼写方式。搜索这个最好的正则表达式是什么?

以下是30个变体的列表:

Gadaffi
Gadafi
Gadafy
Gaddafi
Gaddafy
Gaddhafi
Gadhafi
Gathafi
Ghadaffi
Ghadafi
Ghaddafi
Ghaddafy
Gheddafi
Kadaffi
Kadafi
Kaddafi
Kadhafi
Kazzafi
Khadaffy
Khadafy
Khaddafi
Qadafi
Qaddafi
Qadhafi
Qadhdhafi
Qadthafi
Qathafi
Quathafi
Qudhafi
Kad'afi

目前为止我最好的尝试是:

\b[KG]h?add?af?fi$\b

但我似乎还是遗漏了一些变体。有什么建议吗?


当前回答

从潜在拼写列表中需要注意的一件有趣的事情是,包含的列表中只有3个Soundex值(如果忽略离群值'Kazzafi')

G310, k310, q310

现在,这里存在误报(“Godby”也是G310),但是通过结合有限的变音位命中,可以消除它们。

<?
$soundexMatch = array('G310','K310','Q310');
$metaphoneMatch = array('KTF','KTHF','FTF','KHTF','K0F');

$text = "This is a big glob of text about Mr. Gaddafi. Even using compound-Khadafy terms in here, then we might find Mr Qudhafi to be matched fairly well. For example even with apostrophes sprinkled randomly like in Kad'afi, you won't find false positives matched like godfrey, or godby, or even kabbadi";

$wordArray = preg_split('/[\s,.;-]+/',$text);
foreach ($wordArray as $item){
    $rate = in_array(soundex($item),$soundexMatch) + in_array(metaphone($item),$metaphoneMatch);
    if ($rate > 1){
        $matches[] = $item;
    }
}
$pattern = implode("|",$matches);
$text = preg_replace("/($pattern)/","<b>$1</b>",$text);
echo $text;
?>

稍作调整,再加上一些西里尔字母的音译,您将得到一个相当健壮的解决方案。

其他回答

如果你想避免匹配没有人使用过的东西(即避免倾向于“。+”),你最好的方法是创建一个正则表达式,它只是所有的替代方案(例如。(Qadafi|Kadafi|…))然后将其编译为DFA,然后将DFA转换回正则表达式。假设一个适度合理的实现会给您一个“压缩”正则表达式,它保证不包含意外的变量。

只是一个补充:你应该加上“Gheddafi”作为替代拼写。所以RE应该是

\b[KG]h?[ae]dd?af?fi$\b

一个可能的替代方案是从示例http://regex.inginf.units.it生成正则表达式的在线工具。 给它一个机会吧!

还有什么是以Q, G或K开头,中间有d, z或t,并以人们实际搜索的“fi”结尾的呢?

/\b[GQK].+[dzt].+fi\b/i

完成了。

>>> print re.search(a, "Gadasadasfiasdas") != None
False
>>> print re.search(a, "Gadasadasfi") != None
True
>>> print re.search(a, "Qa'dafi") != None
True

有趣的是,我被否决了。有人能在评论里留下一些假阳性吗?

既然你在匹配小词,为什么不试试用Levenshtein距离的相似度搜索引擎呢?您最多可以允许k次插入或删除。通过这种方式,你可以将距离函数更改为其他更适合特定问题的函数。simMetrics库中有许多可用的函数。