Ich versuche nach dem Wort Gadaffi zu suchen. Was ist der beste reguläre Ausdruck, um danach zu suchen?
Mein bisher bester Versuch ist:
\b[KG]h?add?af?fi$\b
Aber ich vermisse immer noch einige Zeitschriften. Irgendwelche Vorschläge?
Update: Ich habe hier eine ziemlich umfangreiche Liste gefunden: http://blogs.abcnews.com/theworldnewser/2009/09/how-many-different-ways-can-you-spell-gaddafi.html
Die Antwort passt zu allen 30 Varianten:
Gadaffi Gadafi Gadafy Gaddafi Gaddafi Gaddhafi Gaddafi Gathafi Ghadafi Ghadafi Ghaddafi Ghaddafy Gheddafi Kadaffi Kadafi Kaddafi Kadhafi Kazzafi Khadaffy Khadafy Khaddafi Qadafi Qaddafi __. Qadthafi Qathafi Quathafi Qudhafi Kad'afi
\b[KGQ]h?add?h?af?fi\b
Die arabische Transkription ist (Wiki sagt) "Qaḏḏāfī", also das Hinzufügen eines Q. Und eines H ("Gaddafi", wie der Artikel (siehe unten) erwähnt).
Übrigens, warum gibt es am Ende der Regex einen $
?
Übrigens, schöner Artikel zum Thema:
EDIT
Um alle Namen im Artikel zu finden, den Sie später erwähnt haben, sollte dies allen entsprechen. Hoffen wir einfach, dass es nicht mit vielen anderen Sachen übereinstimmt: D
\b(Kh?|Gh?|Qu?)[aeu](d['dt]?|t|zz|dhd)h?aff?[iy]\b
Einfach ... (Qadaffi|Khadafy|Qadafi|
...)
... es ist selbstdokumentiert, wartbar und vorausgesetzt, Ihre Regex-Engine kompiliert tatsächlich reguläre Ausdrücke (anstatt sie zu interpretieren), wird sie mit demselben DFA kompilieren, dass eine eher verschleierte Lösung dies wäre.
Das Schreiben kompakter regulärer Ausdrücke ist wie das Verwenden kurzer Variablennamen, um ein Programm zu beschleunigen. Es hilft nur, wenn Ihr Compiler nicht mehr auf dem Pult ist.
Eine interessante Sache aus Ihrer Liste der möglichen Schreibweisen ist, dass es nur 3 Soundex-Werte für die enthaltene Liste gibt (wenn Sie den Ausreißer 'Kazzafi' ignorieren).
G310, K310, Q310
Nun gibt es falsche Positive ('Godby' ist auch G310), aber durch die Kombination der begrenzten Metaphon-Treffer können Sie sie auch eliminieren.
<?
$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;
?>
Ein paar Verbesserungen und sagen wir einige kyrillische Transliterationen, und Sie haben eine ziemlich robuste Lösung.
Verwendung des CPAN-Moduls 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;
Dies erzeugt den folgenden regulären Ausdruck:
(?-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))
Ich denke, Sie machen es hier zu kompliziert. Der korrekte Regex ist so einfach wie:
\u0627\u0644\u0642\u0630\u0627\u0641\u064a
Es entspricht der Verkettung der sieben arabischen Unicode-Codepunkte, aus denen das Wort القذافي (d. H. Gadaffi) besteht.
Wenn Sie vermeiden möchten, dass die Elemente übereinstimmen, die niemand verwendet hat (dh vermeiden Sie die Tendenz "+"), ist es am besten, einen regulären Ausdruck zu erstellen, der nur aus allen Alternativen besteht (z. ) kompilieren Sie das dann in ein DFA und konvertieren Sie das DFA anschließend wieder in einen regulären Ausdruck. Angenommen, eine gemäßigt sinnvolle Implementierung, die einen "komprimierten" regulären Ausdruck ergibt, der garantiert keine unerwarteten Varianten enthält.
Wenn Sie eine konkrete Auflistung aller 30 Möglichkeiten haben, verketten Sie sie alle mit einem Haufen "ors". Dann können Sie sicher dass es nur genau den Dingen entspricht, die Sie aufgelistet haben, und nicht mehr. Ihre RE-Engine wird wahrscheinlich in der Lage sein, weitere Optimierungen vorzunehmen, und zwar mit 30 Optionen, auch wenn dies nicht der Fall ist. Wenn Sie versuchen, mit der manuellen Umwandlung eines "intelligenten" RE herumzuspielen, kann es unmöglich besser werden, und es kann sich als schlechter erweisen.
(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)
Sicherlich nicht die am meisten optimierte Version. Teilen Sie die Silben auf, um die Anzahl der Übereinstimmungen zu maximieren, und stellen Sie sicher, dass wir keine Fehlalarme erhalten.
Nun, da Sie mit kleinen Wörtern übereinstimmen, warum versuchen Sie nicht eine Ähnlichkeitssuchmaschine mit der Levenshtein Entfernung? Sie können höchstens k Einfügungen oder Löschungen zulassen. Auf diese Weise können Sie die Distanzfunktion auf andere Dinge ändern, die für Ihr spezifisches Problem besser geeignet sind. Die simMetrics-Bibliothek bietet viele Funktionen.
Eine mögliche Alternative ist das Online-Tool zur Erzeugung regulärer Ausdrücke aus den Beispielen http://regex.inginf.units.it .
Warum nicht einen gemischten Ansatz? Etwas zwischen einer Liste aller Möglichkeiten und einem komplizierten Regex, das viel zu viel passt.
Bei Regex geht es um Musterabgleich und ich kann kein Muster für alle Varianten in der Liste sehen. Wenn Sie dies versuchen, finden Sie auch Dinge wie "Gazzafy" oder "Quud'haffi", die höchstwahrscheinlich keine gebrauchte Variante sind und definitiv nicht auf der Liste stehen.
Aber ich kann Muster für einige der Varianten sehen, und so endete ich damit:
\b(?:Gheddafi|Gathafi|Kazzafi|Kad'afi|Qadhdhafi|Qadthafi|Qudhafi|Qu?athafi|[KG]h?add?h?aff?[iy]|Qad[dh]?afi)\b
Am Anfang liste ich diejenigen auf, bei denen ich kein Muster sehen kann, gefolgt von einigen Varianten, bei denen Muster vorhanden sind.
Sehen Sie es hier auf www.rubular.com
Ich weiß, das ist eine alte Frage, aber ...
Keiner dieser beiden Regexes ist der schönste, aber sie sind optimiert und passen beide zu ALL den Variationen im ursprünglichen Beitrag.
"Little Beauty" # 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)
"Little Beauty" # 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
Ruhe in Frieden, Muammar.
Nur ein Nachtrag: Sie sollten "Gheddafi" als alternative Schreibweise hinzufügen. Also sollte das RE sein
\b[KG]h?[ae]dd?af?fi$\b
Was sonst noch mit Q, G oder K anfängt, hat ein d, z oder t in der Mitte und endet in "fi" den Leuten eigentlich Suchen?
/\b[GQK].+[dzt].+fi\b/i
Erledigt.
>>> print re.search(a, "Gadasadasfiasdas") != None
False
>>> print re.search(a, "Gadasadasfi") != None
True
>>> print re.search(a, "Qa'dafi") != None
True
Interessant, dass ich abgelehnt werde. Kann jemand falsche Kommentare in den Kommentaren hinterlassen?
[GQK] [ahu] + [dtez] + '' [adhz] + f {1,2} (i | y)
In Teilen:
Anmerkung: Ich habe gerade Regex gelernt und wollte es versuchen. Wird einen kleinen Fehler später beheben