Я пытаюсь найти слово Гадаффи. Какое лучшее регулярное выражение для поиска?
Моя лучшая попытка:
\b[KG]h?add?af?fi$\b
Но я все еще, кажется, не хватает некоторых журналов. Любые предложения?
Обновление: здесь я нашел довольно обширный список: http://blogs.abcnews.com/theworldnewser/2009/09/how-many-different-ways-can-you-spell-gaddafi.html
Ответ ниже соответствует всем 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[KGQ]h?add?h?af?fi\b
Арабская транскрипция (Wiki говорит) "Qaḏḏāfī", поэтому, возможно, добавление Q. И один H ( "Каддафи", как упоминается в статье (см. ниже)).
Btw, почему существует $
в конце регулярного выражения?
Btw, хорошая статья по теме:
Каддафи, Кадафи или Каддафи? Почему имя ливийских лидеров написано так много разных способов?ИЗМЕНИТЬ
Чтобы соответствовать всем именам в статье, о которой вы упоминали позже, это должно совпадать со всеми. Надеюсь, что это не будет соответствовать многим другим вещам: D
\b(Kh?|Gh?|Qu?)[aeu](d['dt]?|t|zz|dhd)h?aff?[iy]\b
d
также соответствует ḏ?
Easy... (Qadaffi|Khadafy|Qadafi|
... )
... он самодокументирован, поддерживается и предполагает, что ваш механизм regexp фактически компилирует регулярные выражения (а не интерпретирует их), он будет скомпилирован с тем же DFA, что более запутанное решение было бы.
Написание компактных регулярных выражений подобно использованию коротких имен переменных для ускорения работы программы. Это помогает, только если ваш компилятор мертв мозгом.
Интересно отметить из вашего списка потенциальных написаний, что только 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;
?>
Несколько настроек, и давайте скажем, какую-то кириллическую транслитерацию, и у вас будет довольно надежное решение.
Использование модуля CPAN Regexp:: Assemble:
#!/usr/bin/env perl
use Regexp::Assemble;
my $ra = Regexp::Assemble->new;
$ra->add($_) for qw(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);
say $ra->re;
Это приводит к следующему регулярному выражению:
(?-xism:(?:G(?:a(?:d(?:d(?:af[iy]|hafi)|af(?:f?i|y)|hafi)|thafi)|h(?:ad(?:daf[iy]|af?fi)|eddafi))|K(?:a(?:d(?:['dh]a|af?)|zza)fi|had(?:af?fy|dafi))|Q(?:a(?:d(?:(?:(?:hd)?|t)h|d)?|th)|u(?:at|d)h)afi))
Думаю, ты слишком усложняешь ситуацию. Правильное регулярное выражение так же просто, как:
\u0627\u0644\u0642\u0630\u0627\u0641\u064a
Он соответствует конкатенации семи арабских кодов Unicode, которые образуют слово القذافي (т.е. Gadaffi).
Если вы хотите избежать соответствия тем, которые никто не использовал (т.е. избегать стремления к "+" ), ваш лучший подход заключался бы в том, чтобы создать регулярное выражение, которое содержит все альтернативы (например, Qadafi | Kadafi |...)) затем скомпилируйте это в DFA, а затем преобразуйте DFA обратно в регулярное выражение. Предполагая умеренно разумную реализацию, которая даст вам "сжатое" регулярное выражение, гарантирующее, что не будет содержать неожиданных вариантов.
Если у вас есть конкретный список из всех 30 возможностей, просто соедините их все вместе с кучей "ors". Тогда вы можете быть уверены, что он соответствует только тем вещам, которые вы указали, и не более того. Вероятно, ваш движок RE сможет оптимизировать его, и, конечно же, с 30 вариантами, даже если это еще не так. Пытаться возиться с ручным превращением его в "умный" RE, не может оказаться лучше и может ухудшиться.
(G|Gh|K|Kh|Q|Qh|Q|Qu)(a|au|e|u)(dh|zz|th|d|dd)(dh|th|a|ha|)(\x27|)(a|)(ff|f)(i|y)
Конечно, не самая оптимизированная версия, разбитая на слоги, чтобы максимизировать совпадения, пытаясь убедиться, что мы не получаем ложных срабатываний.
Хорошо, поскольку вы соответствуете маленьким словам, почему бы вам не попробовать поисковую систему подобия с Levenshtein расстояние? Вы можете разрешить не более k вставок или удалений. Таким образом, вы можете изменить функцию расстояния на другие вещи, которые лучше работают для вашей конкретной проблемы. В библиотеке simMetrics имеется множество функций.
Возможной альтернативой является онлайн-инструмент для генерации регулярных выражений из примеров http://regex.inginf.units.it. Дайте ему шанс!
Я знаю, что это старый вопрос, но...
Ни одно из этих двух регулярных выражений не является самым красивым, но они оптимизированы и оба соответствуют ALL вариантам исходного сообщения.
"Маленькая красавица" # 1
(?:G(?:a(?:d(?:d(?:af[iy]|hafi)|af(?:f?i|y)|hafi)|thafi)|h(?:ad(?:daf[iy]|af?fi)|eddafi))|K(?:a(?:d(?:['dh]a|af?)|zza)fi|had(?:af?fy|dafi))|Q(?:a(?:d(?:(?:(?:hd)?|t)h|d)?|th)|u(?:at|d)h)afi)
"Маленькая красавица" # 2
(?:(?:Gh|[GK])adaff|(?:(?:Gh|[GKQ])ad|(?:Ghe|(?:[GK]h|[GKQ])a)dd|(?:Gadd|(?:[GKQ]a|Q(?:adh|u))d|(?:Qad|(?:Qu|[GQ])a)t)h|Ka(?:zz|d'))af)i|(?:Khadaff|(?:(?:Kh|G)ad|Gh?add)af)y
Отдых в мире, Муаммар.
Почему бы не сделать смешанный подход? Что-то между списком всех возможностей и сложным Regex, который слишком много соответствует.
Regex - это сопоставление с образцом, и я не вижу шаблон для всех вариантов в списке. Пытаясь сделать это, также найдутся такие вещи, как "Газзафи" или "Куддхаффи", которые, скорее всего, не используются и, безусловно, не входят в список.
Но я могу видеть шаблоны для некоторых вариантов, и поэтому я закончил с этим:
\b(?:Gheddafi|Gathafi|Kazzafi|Kad'afi|Qadhdhafi|Qadthafi|Qudhafi|Qu?athafi|[KG]h?add?h?aff?[iy]|Qad[dh]?afi)\b
В начале я перечисляю те, где я не вижу шаблон, а затем некоторые варианты, где есть шаблоны.
См. здесь www.rubular.com
\b
включены только в первый и последний варианты.
Что еще начинается с 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
Интересно, что меня забирают. Может ли кто-нибудь оставить некоторые ложные срабатывания в комментариях?
kartografi kryptografi Gaddafi Qaddafi gadafi gaddafi katastloofi katastorfi katastrofi khadaffi kadafi kardiyografi gaskromatografi kardiografi kinematografi kromatografi krystallografi kulturgeografi gandolfi grizzaffi gadhafi kadaffi kaddafi khaddafi qaddafi qadhafi quedaffi gordonsCHsKFI
. Однако некоторые из них не являются ложными срабатываниями.
[iy]
вместо просто i
: gelatinify gentrify ghostlify giddify gladify goutify gratify "Gyula Dessewffy" katasrofy katastrofy khadafy quantify quasi-deify quizzify
Просто добавление: вы должны добавить "Геддафи" в качестве альтернативного написания. Таким образом, RE должен быть
\b[KG]h?[ae]dd?af?fi$\b