Регулярное выражение для поиска Gadaffi


361

Я пытаюсь найти слово Gadaffi. Какое регулярное выражение лучше всего искать?

Моя лучшая попытка на данный момент:

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

Но мне все еще не хватает некоторых журналов. Какие-либо предложения?

Обновление: я нашел довольно обширный список здесь: http://blogs.abcnews.com/theworldnewser/2009/09/how-many-different-ways-can-you-spell-gaddafi.html

Ответ ниже соответствует всем 30 вариантам:

Каддафи
Gadafi
Gadafy
Каддафи
Gaddafy
Gaddhafi
М.Каддафи
Каддафи
Ghadaffi
Каддафи
Каддафи
Ghaddafy
Gheddafi
Кадаффи
Кадафи
Каддафи
Каддафи
Kazzafi
Khadaffy
Khadafy
Khaddafi
Qadafi
Каддафи
Каддафи
Qadhdhafi
Qadthafi
Qathafi
Quathafi
Qudhafi
Kad'afi

8
Какие из них вам не хватает? И где вы ищете, есть ли веб-поиск с регулярным выражением?
Czechchnology

43
Всегда публикуются новые журналы, поэтому, если они будут продолжать писать о Gadaffi, вы будете стремиться .+быть единственным действительным регулярным выражением.
Мойнудин

30
Я обнаружил, что эта картина помогает с различными написаниями: upload.wikimedia.org/math/6/1/f/…
KLee1

24
Как обычно, Lisp реализовал это первым - foldr.org/~michaelw/projects/regex/regexp-test-suite.lisp (прокрутка примерно на полпути вниз)
Даниэль С. Стерлинг

7
@Daniel Sterling: на самом деле, тест Khadafy является частью GNU grep testsuite с момента первоначальной фиксации в RCS (вт. 3 ноября 21:38:52 1998 +0000), и, вероятно, даже старше этого!
Паоло Бонзини

Ответы:


138

\b[KGQ]h?add?h?af?fi\b

Арабская транскрипция (Wiki говорит) «Qaḏḏāfī», так что, возможно, добавление Q. И одного H («Каддафи», как упоминается в статье (см. Ниже)).

Кстати, почему есть $в конце регулярного выражения?


Кстати, хорошая статья на тему:

Каддафи, Каддафи или Каддафи? Почему имя ливийского лидера пишется так по-разному? ,


РЕДАКТИРОВАТЬ

Чтобы соответствовать всем именам в статье, которую вы упомянули позже , это должно соответствовать им всем. Будем надеяться, что это не будет соответствовать многим другим вещам: D

\b(Kh?|Gh?|Qu?)[aeu](d['dt]?|t|zz|dhd)h?aff?[iy]\b

$ Неправильный, я сначала сопоставил конец строки, забыл удалить его.
SiggyF

Есть ли dтакже соответствовать ð?
SiggyF

2
@DiggyF, нет, я просто подумал, что если арабская транскрипция говорит Qaḏḏāfī, регулярное выражение Qaddafiтоже должно проверять . Если вы хотите поискать и арабскую транскрипцию, просто поищите ее - я не думаю, что есть больше вариантов арабской транскрипции, только для английской транскрипции.
Czechchnology

@DiggyF, я отредактировал более длинное регулярное выражение, которое соответствует всем именам в статье, которую вы опубликовали (кроме двух с ?вместо букв). Хотя это может быть излишним.
Czechchnology

2
Это также соответствует «Quuzzafi» и куче других ложных срабатываний, хотя я полагаю, что при поиске в новостях и т. Д. Это не будет иметь большого значения.
Бен w

275

Легко ... (Qadaffi|Khadafy|Qadafi|... )... он самодокументирован, поддерживается и, если ваш механизм регулярных выражений на самом деле компилирует регулярные выражения (а не интерпретирует их), он скомпилирует тот же DFA, что и более запутанное решение.

Написание компактных регулярных выражений похоже на использование коротких имен переменных для ускорения программы. Это помогает, только если ваш компилятор не работает.


23
Отличный ответ! Люди используют регулярные выражения гораздо чаще, чем заботятся о том, как они на самом деле работают.
Томас Але

3
Мне также очень нравится простота этого решения, но я удивлен, что это скомпилируется в тот же DFA. У вас есть ссылка, которая говорит об этом? Интуитивно кажется, что это может быть менее эффективно, чем ранее созданное регулярное выражение или ответ ниже, который предлагает использовать модуль Perl Regexp :: Assemble в том же списке имен or'd.
Риан Сандерсон

6
-1 Смысл регулярного выражения состоит в том, чтобы сократить то, что часто может быть - как это в данном случае - очень длинный список альтернатив относительно короткой формуле. Результат часто может выполняться быстрее, чем выполнение неоптимизированного исчерпывающего поиска.
Мартино

7
Вы правы, что цель регулярных выражений состоит в том, чтобы предоставить компактное, четкое представление для большого набора значений. Но основная концепция состоит в том, чтобы представить регулярное выражение и сказать «все, что соответствует этому, хорошо». То есть предполагается, что у вас есть свобода включать что-либо систематическое. Здесь мы имеем противоположную ситуацию: варианты написания (и варианты, которые никогда не появляются) являются едва ли не этой стороной «совершенно случайного». Сложные попытки «компактности» получают очень низкие баллы за «чистоту»!
Джекр

1
Также ознакомьтесь с алгоритмом Aho-Corasick, который оптимален для одновременного поиска строк: en.wikipedia.org/wiki/…
Thomas Ahle

45

Из вашего списка возможных вариантов написания можно отметить одну интересную вещь: в содержащемся списке есть только 3 значения Soundex (если вы игнорируете выброс «Kazzafi»)

G310, K310, Q310

Теперь там есть ложные срабатывания («Годби» также называется 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;
?>

Несколько настроек и, скажем, некоторая транслитерация кириллицы, и у вас будет довольно надежное решение.


2
Обратите внимание, что soundex специализируется на английском языке, существуют другие фонетические алгоритмы для других языков с другими правилами произношения
Incognito

8
Хотя это правда, мы находимся в странной ситуации здесь. Основной запрос был «Я пытаюсь найти слово Gadaffi», но я чувствую, что регулярное выражение было красной сельдью. Не существует сборника правил транслитерации на арабский и латинский языки, и поэтому обращение к регулярному выражению из списка не будет полностью отвечать первоначальному запросу.
tomwalsham

2
Я чувствую, что система нечеткого соответствия лучше подходит, но собственный алгоритм кажется излишним. Использование комбинации soundex-metaphone, по-видимому, работает так же хорошо, как и решение regex, позволяя создавать дополнительные непредвиденные варианты написания, в то же время просто используя готовые алгоритмы.
tomwalsham

Использование metaphone2 и metaphone3 приводит к лучшим результатам (т. Е. Почти все в metaphone2 - это KDF, а metaphone1 - не совсем). Однако Metaphone3 стоит около 40 долларов.
Инкогнито

27

Используя модуль 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))

23

Я думаю, что вы здесь все усложняете. Правильное регулярное выражение так же просто, как:

\u0627\u0644\u0642\u0630\u0627\u0641\u064a

Это соответствует объединению семи арабских кодовых точек Unicode, которые образуют слово القذافي (т.е. Gadaffi).


3
Далее просто отправьте nytimes.com через Google Translate, и Боб станет вашим дядей.
Роберт Россни

19

Если вы хотите избежать сопоставления вещей, которые никто не использовал (то есть избегать стремления к «. +»), Ваш лучший подход - создать регулярное выражение, содержащее только все альтернативы (например, (Qadafi | Kadafi | ...) ) затем скомпилируйте это в DFA, а затем преобразуйте DFA обратно в регулярное выражение. Предполагая умеренно разумную реализацию, которая даст вам «сжатое» регулярное выражение, которое гарантированно не будет содержать неожиданные варианты.


2
Я знаю, что это возможно там, но как бы вы это сделали на практике (используя, например, какой-то общий динамический язык)
Рори

3
Я понимаю теорию, стоящую за этим, но, как и @Rory, мне также интересно узнать, как бы вы на самом деле сделали это на практике.
dancavallaro

да, я думал об этом, чтобы дать лучший ответ, но сейчас я немного занят. у меня есть некоторый (некрасивый и плохо документированный) код на code.google.com/p/lepl/source/browse/src/lepl/regexp/core.py, который создает dfa из регулярного выражения (фактически, анализатор находится в другом классе , но тяжелая работа есть, вы идете regexp -> nfa -> dfa). перейти от dfa к регулярному выражению легко (я думаю?).
Эндрю Кук

на самом деле, документация там лучше, чем я помню: o) основная идея заключается в том, что вы описываете регулярное выражение в терминах классов в верхней части файла. тогда его можно довольно легко перевести на nfa (на самом деле nfa - это просто набор переходов, говорящих «если вы получите это письмо, то вы можете перейти сюда или сюда ...», это довольно легко понять). тогда dfa - это своего рода «расширенная» версия того, где вы избегаете возврата; это сделано NfaToDfa (и это сложная часть). тогда dfa может выступать как само регулярное выражение, которое записывается как очень сложные наборы символов (?!)
Эндрю Кук

10

Если у вас есть конкретный список всех 30 возможностей, просто объедините их вместе с кучей «или». Тогда вы можете быть уверены, что он соответствует только тем вещам, которые вы перечислили, и не более. Ваш двигатель RE, вероятно, сможет оптимизировать в дальнейшем, и, ну, с 30 вариантами выбора, даже если это не так, это все же не имеет большого значения. Попытка возиться с ручным превращением его в «умный» RE не может быть лучше и может оказаться хуже.


9
(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)

Конечно, не самая оптимизированная версия, разделить на слоги, чтобы максимизировать совпадения, пытаясь убедиться, что мы не получаем ложных срабатываний.


7

Ну, так как вы сопоставляете маленькие слова, почему бы вам не попробовать поисковую систему схожести с расстоянием Левенштейна ? Вы можете разрешить не более k вставок или удалений. Таким образом, вы можете изменить функцию расстояния на другие вещи, которые лучше подходят для вашей конкретной задачи. В библиотеке simMetrics доступно много функций.


4

Возможной альтернативой является онлайн-инструмент для генерации регулярных выражений из примеров http://regex.inginf.units.it . Дай этому шанс!


1

Почему бы не сделать смешанный подход? Что-то среднее между списком всех возможностей и сложным регулярным выражением, которое слишком сильно совпадает.

Regex - это сопоставление с образцом, и я не вижу шаблон для всех вариантов в списке. Попытка сделать это также найдет такие вещи, как «Gazzafy» или «Quud'haffi», которые, скорее всего, не являются используемым вариантом и определенно отсутствуют в списке.

Но я вижу шаблоны для некоторых вариантов, и в итоге я получил следующее:

\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только включены в первом и последней альтернативе.
Кристофер Кройциг

1

Я знаю, что это старый вопрос, но ...

Ни один из этих двух регулярных выражений не является самым красивым, но они оптимизированы и оба соответствуют ВСЕМ вариантам в оригинальном посте.

"Маленькая красавица" # 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

Покойся с миром, Муамар.


0

Просто дополнение: вы должны добавить «Gheddafi» в качестве альтернативного написания. Таким образом, RE должно быть

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

0

[GQK] [ах] + [dtez] + \ '[adhz] + ж {1,2} (я | у)?

По частям:

  • [GQK]
  • [Ах] +
  • [Dtez] +
  • \ '?
  • [Adhz] +
  • е {1,2} (я | у)

Примечание: просто хотел попробовать.


-1

Что еще начинается с Q, G или K, имеет ad, 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

Интересно, что меня опускают. Может кто-то оставить ложные срабатывания в комментариях?


2
Из крекинг словаря , который я случиться, что сидеть: 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 . Однако некоторые из них не являются ложными срабатываниями.
BMDan

2
И дополнения к этому списку, которые являются результатом [iy]только вместо i:gelatinify gentrify ghostlify giddify gladify goutify gratify "Gyula Dessewffy" katasrofy katastrofy khadafy quantify quasi-deify quizzify
BMDan
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.