Wyrażenie regularne do wyszukiwania Gadaffi

361

Próbuję wyszukać słowo Gadaffi. Jakie jest najlepsze wyrażenie regularne do wyszukiwania?

Jak dotąd moja najlepsza próba to:

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

Ale nadal wydaje mi się, że brakuje mi niektórych czasopism. Jakieś sugestie?

Aktualizacja: Znalazłem dość obszerną listę tutaj: http://blogs.abcnews.com/theworldnewser/2009/09/how-many-different-ways-can-you-spell-gaddafi.html

Poniższa odpowiedź pasuje do wszystkich 30 wariantów:

Gadaffi
Kadafi
Gadafij
Kadafi
Kadafi
Kaddafiego
Kaddafiego
Gathafi
Ghadaffi
Ghadafi
Ghaddafi
Ghaddafy
Gheddafi
Kadaffi
Kadafi
Kadafi
Kaddafi
Kazzafi
Khadaffy
Khadafy
Khaddafi
Kadafi
Kadafi
Kaddafi
Kaddafi
Kadafi
Qathafi
Quathafi
Qudhafi
Kad'afi
SiggyF
źródło
8
Których brakuje? A gdzie szukasz, czy istnieje wyszukiwarka internetowa z regex?
Czechnology
43
Zawsze publikowane są nowe czasopisma, więc jeśli nadal będą pisać o Gadaffi, będziesz miał tendencję do .+bycia jedynym ważnym wyrażeniem regularnym.
moinudin
30
Przekonałem
KLee1
24
Jak zwykle Lisp zaimplementował ten pierwszy - foldr.org/~michaelw/projects/regex/regexp-test-suite.lisp (przewiń w połowie drogi)
Daniel S. Sterling
7
@Daniel Sterling: w rzeczywistości test Khadafy jest częścią strony testowej GNU grep od czasu pierwszego zatwierdzenia do RCS (Wt 3 listopada 21:38:52 1998 +0000) i prawdopodobnie jest nawet starszy!
Paolo Bonzini

Odpowiedzi:

138

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

Arabska transkrypcja to (mówi Wiki) „Qaḏḏāfī”, więc może dodać Q. I jeden H („Gadhafi”, jak wspomniano w artykule (patrz poniżej)).

Przy okazji, dlaczego jest $na końcu wyrażenia regularnego?


Przy okazji fajny artykuł na ten temat:

Kadafi, Kadafi czy Kadafi? Dlaczego imię lidera Libii jest pisane na tak wiele różnych sposobów? .


EDYTOWAĆ

Aby dopasować wszystkie nazwy w artykule, o którym wspominałeś później , powinno to być zgodne dla wszystkich. Miejmy nadzieję, że nie będzie pasować do wielu innych rzeczy: D

\b(Kh?|Gh?|Qu?)[aeu](d['dt]?|t|zz|dhd)h?aff?[iy]\b
Czechnologia
źródło
$ Jest źle, najpierw dopasowałem koniec linii, zapomniałem go usunąć.
SiggyF
Czy dpasuje również do ḏ?
SiggyF,
2
@DiggyF, nie, pomyślałem tylko, że jeśli arabska transkrypcja mówi Qaḏḏāfī, regex też powinien to sprawdzić Qaddafi. Jeśli chcesz też poszukać arabskiej transkrypcji, po prostu poszukaj jej - nie sądzę, żeby było więcej wariantów arabskiej transkrypcji, tylko angielskich.
Czechnology
@DiggyF, edytowałem dłuższe wyrażenie, które pasuje do wszystkich nazw w opublikowanym artykule (oprócz dwóch z ?literami zamiast zamiast). Może to być przesada.
Czechnology
2
To również pasuje do „Quuzzafi” i wielu innych fałszywych wyników pozytywnych, choć przypuszczam, że przy przeszukiwaniu wiadomości itp. Nie będzie to miało większego znaczenia.
ben w
275

Łatwo (Qadaffi|Khadafy|Qadafi|...) ... jest to samo udokumentowane, utrzymaniu, a przy założeniu, że silnik regexp faktycznie kompiluje wyrażenia regularne (zamiast je interpretować), skompiluje się do tego samego DFA, co rozwiązanie bardziej zaciemnione.

Pisanie kompaktowych wyrażeń regularnych przypomina używanie krótkich nazw zmiennych w celu przyspieszenia programu. Pomaga to tylko wtedy, gdy twój kompilator jest martwy.

Chris Pacejo
źródło
23
Świetna odpowiedź! Ludzie używają wyrażeń regularnych znacznie częściej niż zależy im na tym, jak naprawdę działają.
Thomas Ahle,
3
Bardzo podoba mi się również prostota tego rozwiązania, ale jestem zaskoczony, że skompiluje się on do tego samego DFA. Czy masz link, który mówi o tym? Intuicyjnie wydaje się, że może to być mniej wydajne niż poprzednio spreparowane wyrażenie regularne lub odpowiedź poniżej, która sugeruje użycie modułu perl Regexp :: Assemble na tej samej liście nazw lub nazw.
Rian Sanderson
6
-1 Istotą wyrażenia regularnego jest ograniczenie tego, co często może być - tak jak w tym przypadku - bardzo długą listą alternatyw dla stosunkowo krótkiej formuły. Wynik często może być wykonywany szybciej niż robienie tego, co jest zasadniczo niezoptymalizowanym, wyczerpującym wyszukiwaniem.
martineau,
7
Masz rację, że celem wyrażeń regularnych jest zapewnienie zwartej, przejrzystej reprezentacji dużego zestawu wartości. Ale podstawową koncepcją jest przedstawienie wyrażenia regularnego i powiedzenie „wszystko, co pasuje do tego, jest dobre”. Oznacza to, że zakładasz, że masz swobodę włączania czegokolwiek systematycznego. W tym przypadku mamy do czynienia z odwrotną sytuacją: warianty pisowni (i wariacje, które nigdy się nie pojawiają) są ledwo po tej stronie „całkowicie losowych”. Opracowane próby „kompaktowania” otrzymują bardzo niskie punkty za „czystość”!
jackr
1
Sprawdź także algorytm Aho-Corasicka, który jest optymalny do równoczesnego wyszukiwania ciągów: en.wikipedia.org/wiki/...
Thomas Ahle
45

Jedną z interesujących rzeczy na liście potencjalnych pisowni jest to, że dla zawartej listy są tylko 3 wartości Soundex (jeśli zignorujesz wartość odstającą „Kazzafi”)

G310, K310, Q310

Teraz są tam fałszywe alarmy („Godby” to także G310), ale łącząc również ograniczone trafienia metafonowe, możesz je wyeliminować.

<?
$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;
?>

Kilka drobnych poprawek i powiedzmy trochę cyrylicy, a otrzymasz dość solidne rozwiązanie.

tomwalsham
źródło
2
Uwaga: soundex specjalizuje się w języku angielskim, istnieją inne algorytmy fonetyczne dla innych języków o różnych zasadach wymowy
Incognito
8
Chociaż to prawda, jesteśmy tutaj w dziwnej sytuacji. Główną prośbą było „Próbuję wyszukać słowo Gadaffi”, ale wydaje mi się, że regex był czerwonym śledziem. Nie ma instrukcji dotyczących transliteracji języka arabskiego-> łacińskiego i dlatego odwrócenie wyrażenia regularnego z listy nie będzie w pełni odpowiadać pierwotnemu żądaniu.
tomwalsham
2
Wydaje mi się, że system dopasowywania rozmytego jest bardziej odpowiedni, ale niestandardowy algorytm wydaje się przesadny. Wydaje się, że używanie kombinacji soundex-metafon działa równie dobrze, jak rozwiązanie wyrażenia regularnego, pozwalając na dalsze nieoczekiwane pisowni, przy jednoczesnym użyciu gotowych alg.
tomwalsham
Korzystanie z metaphone2 i metaphone3 prowadzi do lepszych wyników (tj. Prawie wszystko w metaphone2 to KDF, gdzie jako metaphone1 nie jest całkiem). Metaphone3 kosztuje jednak około 40 dolców.
Incognito
27

Korzystanie z modułu 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;

Daje to następujące wyrażenie regularne:

(?-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))
Prakash K
źródło
23

Myślę, że przesadzasz. Prawidłowe wyrażenie regularne jest tak proste, jak:

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

Odpowiada konkatenacji siedmiu punktów kodu Unicode arabskiego, które tworzą słowo القذافي (tj. Gadaffi).

Staffan Nöteberg
źródło
3
Następnie po prostu potokuj nytimes.com przez Tłumacza Google, a Bob jest twoim wujem.
Robert Rossney,
19

Jeśli chcesz uniknąć dopasowywania rzeczy, których nikt nie użył (tj. Unikaj tendencji do „. +”), Najlepszym rozwiązaniem byłoby utworzenie wyrażenia regularnego zawierającego tylko wszystkie alternatywy (np. (Qadafi | Kadafi | ...) ), a następnie skompiluj to w DFA, a następnie przekonwertuj DFA z powrotem na wyrażenie regularne. Zakładając umiarkowanie sensowną implementację, która dałaby ci „skompresowane” wyrażenie regularne, które z pewnością nie zawiera nieoczekiwanych wariantów.

Andrzej Cooke
źródło
2
Wiem, że jest to teoretycznie możliwe, ale jak byś to zrobił w praktyce (używając na przykład jakiegoś wspólnego dynamicznego języka)
Rory
3
Rozumiem teorię, ale tak jak @Rory, jestem również zainteresowany tym, jak byś to zrobił w praktyce.
dancavallaro
tak, myślałem o zrobieniu tego, aby dać lepszą odpowiedź, ale w tej chwili jestem trochę zajęty. Mam trochę (brzydki i słabo udokumentowany) kod na code.google.com/p/lepl/source/browse/src/lepl/regexp/core.py, który konstruuje dfa z wyrażenia regularnego (właściwie parser jest w innej klasie , ale ciężka praca jest tam; idziesz regexp -> nfa -> dfa). przejście od dfa do regexp jest łatwe (myślę?).
Andrew Cooke
tak naprawdę dokumentacja jest lepsza niż pamiętam: o) podstawową ideą jest opisanie wyrażenia regularnego w kategoriach klas u góry pliku. które następnie można dość łatwo przetłumaczyć na nfa (nfa to tak naprawdę zestaw przejść mówiący „jeśli dostaniesz ten list, niż możesz przejść tutaj lub tutaj ...” jest to dość łatwe do zrozumienia). dfa jest więc rodzajem „rozszerzonej” wersji tej, w której unikasz konieczności cofania się; robi to NfaToDfa (i jest to trudna część). DFA może być traktowane jako wyrażenie regularne, napisane jako bardzo złożone zestawy znaków (?!)
Andrew Cooke
10

Jeśli masz konkretną listę wszystkich 30 możliwości, po prostu połącz je wszystkie z kilkoma „orami”. Dzięki temu możesz mieć pewność , że pasuje ono tylko do dokładnie wymienionych rzeczy, i nic więcej. Twój silnik RE prawdopodobnie będzie w stanie dalej optymalizować i, no cóż, z 30 wyborami, nawet jeśli nie, to nadal nie jest wielka sprawa. Próba manipulacji z ręcznym przekształceniem go w „sprytną” RE nie może być lepsza i może okazać się gorsza.

Jeremy Bowers
źródło
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)

Z pewnością nie jest to najbardziej zoptymalizowana wersja, podzielona na sylaby, aby zmaksymalizować dopasowania, jednocześnie starając się nie dopuścić do fałszywych trafień.

Podstępny
źródło
7

Skoro dopasowujesz małe słowa, dlaczego nie wypróbować wyszukiwarki podobieństwa z odległością Levenshteina ? Możesz zezwolić na maksymalnie k wstawiania lub usuwania. W ten sposób możesz zmienić funkcję odległości na inne, które działają lepiej w przypadku konkretnego problemu. W bibliotece simMetrics dostępnych jest wiele funkcji.

Arnoldo Muller
źródło
4

Możliwą alternatywą jest internetowe narzędzie do generowania wyrażeń regularnych z przykładów http://regex.inginf.units.it . Daj temu szansę!

mimmuz
źródło
1

Dlaczego nie zastosować podejścia mieszanego? Coś między listą wszystkich możliwości a skomplikowanym Regexem, który pasuje zbyt wiele.

Regex dotyczy dopasowywania wzorów i nie widzę wzoru dla wszystkich wariantów na liście. Próbując to zrobić, znajdziesz również takie rzeczy jak „Gazzafy” lub „Quud'haffi”, które najprawdopodobniej nie są używanym wariantem i zdecydowanie nie są na liście.

Ale widzę wzory dla niektórych wariantów, więc skończyłem z tym:

\b(?:Gheddafi|Gathafi|Kazzafi|Kad'afi|Qadhdhafi|Qadthafi|Qudhafi|Qu?athafi|[KG]h?add?h?aff?[iy]|Qad[dh]?afi)\b

Na początku wymieniam te, w których nie widzę wzoru, a następnie kilka wariantów, w których są wzory.

Zobacz tutaj na www.rubular.com

stema
źródło
Twoje \bsą uwzględnione tylko w pierwszej i ostatniej alternatywie.
Christopher Creutzig
1

Wiem, że to stare pytanie, ale ...

Żadne z tych dwóch wyrażeń regularnych nie jest najładniejsze, ale są one zoptymalizowane i oba pasują do WSZYSTKICH odmian oryginalnego postu.

„Mała piękność” nr 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)

„Mała piękność” # 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

Spoczywaj w pokoju, Muammar.

zx81
źródło
0

Tylko dodatek: należy dodać „Gheddafi” jako alternatywną pisownię. Tak powinno być RE

\b[KG]h?[ae]dd?af?fi$\b
Vito De Tullio
źródło
0

[GQK] [ahu] + [dtez] + \ '? [Adhz] + f {1,2} (i | y)

W częściach:

  • [GQK]
  • [ahu] +
  • [dtez] +
  • \ '?
  • [adhz] +
  • f {1,2} (i | y)

Uwaga: Chciałem tylko spróbować.

Dinko Pehar
źródło
-1

Co jeszcze zaczyna się od Q, G lub K, ma reklamę, z lub t w środku, a kończy na „fi”, którego ludzie naprawdę szukają?

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

Gotowy.

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

Ciekawe, że jestem doceniany. Czy ktoś może zostawić w komentarzach fałszywe alarmy?

Motek
źródło
2
Z krakingu słowniku, że zdarzy się, że siedzą: 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 . Niektóre z nich nie są jednak fałszywie pozytywne.
BMDan
2
I dodatki do tej listy, które wynikają z zakończenia [iy]zamiast po prostu i:gelatinify gentrify ghostlify giddify gladify goutify gratify "Gyula Dessewffy" katasrofy katastrofy khadafy quantify quasi-deify quizzify
BMDan