Expresión regular para buscar Gadaffi


361

Estoy tratando de buscar la palabra Gadaffi. ¿Cuál es la mejor expresión regular para buscar esto?

Mi mejor intento hasta ahora es:

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

Pero todavía parece que me faltan algunas revistas. ¿Alguna sugerencia?

Actualización: encontré una lista bastante extensa aquí: http://blogs.abcnews.com/theworldnewser/2009/09/how-many-different-ways-can-you-spell-gaddafi.html

La respuesta a continuación coincide con las 30 variantes:

Gadaffi
Gadafi
Gadafy
Gadafi
Gaddafy
Gadafi
Gadafi
Gathafi
Ghadaffi
Gadafi
Gadafi
Gadada
Gadafi
Kadaffi
Kadafi
Gadafi
Gadafi
Kazzafi
Khadaffy
Khadafy
Khaddafi
Qadafi
Gadafi
Gadafi
Gadafi
Gadafi
Gatafi
Quathafi
Qudhafi
Gadafi

8
¿Cuáles te estás perdiendo? ¿Y dónde estás buscando? ¿Hay una búsqueda web con expresiones regulares?
Czechnology

43
Siempre se publican nuevas revistas, por lo que si siguen escribiendo sobre Gadaffi, tenderá a .+ser la única expresión regular válida.
Moinudin

30
Descubrí que esta imagen ayuda con las diferentes ortografías: upload.wikimedia.org/math/6/1/f/…
KLee1

24
Como de costumbre, Lisp implementó esto primero: foldr.org/~michaelw/projects/regex/regexp-test-suite.lisp (desplácese hasta la mitad)
Daniel S. Sterling

77
@Daniel Sterling: en realidad, la prueba de Khadafy es parte de la prueba de GNU grep desde el compromiso inicial con RCS (martes 3 de noviembre 21:38:52 1998 +0000), ¡y probablemente sea incluso más antigua que eso!
Paolo Bonzini

Respuestas:


138

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

La transcripción en árabe es (Wiki dice) "Qaḏḏāfī", así que quizás agregue una Q. Y una H ("Gadhafi", como menciona el artículo (ver más abajo)).

Por cierto, ¿por qué hay un $al final de la expresión regular?


Por cierto, buen artículo sobre el tema:

Gadafi, Kadafi o Gadafi? ¿Por qué el nombre del líder libio se deletrea de muchas maneras diferentes? .


EDITAR

Para hacer coincidir todos los nombres en el artículo que mencionó más adelante , esto debería coincidir con todos. Esperemos que no coincida con muchas otras cosas: D

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

El $ está mal, estaba haciendo coincidir el final de las líneas primero, olvidé eliminarlo.
SiggyF

¿ dTambién coincide con un ḏ?
SiggyF

2
@DiggyF, no, solo pensé que si la transcripción árabe dice Qaḏḏāfī, la expresión regular también debería verificar Qaddafi. Si también desea buscar la transcripción árabe, solo busque esa; no creo que haya más variantes de la transcripción árabe, solo de las transcripciones en inglés.
Czechnology

@DiggyF, he editado en una expresión regular más larga que coincide con todos los nombres en el artículo que has publicado (excepto los dos con en ?lugar de letras). Sin embargo, podría ser una exageración.
Czechnology

2
Esto también coincide con 'Quuzzafi' y un montón de otros falsos positivos, aunque supongo que al buscar en los informes de noticias, etc., eso no importará mucho.
ben w

275

Fácil ... (Qadaffi|Khadafy|Qadafi|... )... está auto documentado, se puede mantener, y suponiendo que su motor regexp realmente compila expresiones regulares (en lugar de interpretarlas), se compilará en el mismo DFA que una solución más ofuscada.

Escribir expresiones regulares compactas es como usar nombres de variables cortos para acelerar un programa. Solo ayuda si tu compilador tiene muerte cerebral.


23
¡Gran respuesta! Las personas usan expresiones regulares con mucha más frecuencia de lo que les importa cómo funcionan realmente.
Thomas Ahle

3
También me gusta la simplicidad de esta solución, pero me sorprende que se compile en el mismo DFA. ¿Tienes un enlace que habla de esto? Intuitivamente, esto parece que podría ser menos eficiente que la expresión regular previamente diseñada o la respuesta a continuación que sugiere usar el módulo perl Regexp :: Assemble en la misma lista de nombres o nombres.
Rian Sanderson

66
-1 El objetivo de una expresión regular es reducir lo que a menudo puede ser, como es en este caso, una lista muy larga de alternativas a una fórmula relativamente corta. El resultado a menudo puede ejecutarse más rápido que hacer lo que es esencialmente una búsqueda exhaustiva no optimizada.
Martineau

77
Tiene razón, que el objetivo de las expresiones regulares es proporcionar una representación compacta y clara para un gran conjunto de valores. Pero el concepto básico es presentar una expresión regular y decir "todo lo que coincida con esto es bueno". Es decir, supone que tiene la libertad de incluir cualquier cosa sistemática. Aquí, tenemos la situación opuesta: la ortografía variante (y las variaciones que nunca aparecen) son apenas este lado de "completamente al azar". ¡Los elaborados intentos de "compacto" obtienen puntos muy bajos para "claro"!
jackr

1
Consulte también el algoritmo Aho-Corasick, que es óptimo para la búsqueda simultánea de cadenas: en.wikipedia.org/wiki/…
Thomas Ahle

45

Una cosa interesante de su lista de posibles deletreos es que solo hay 3 valores Soundex para la lista contenida (si ignora el 'Kazzafi' atípico)

G310, K310, Q310

Ahora, hay falsos positivos allí ('Godby' también es G310), pero al combinar también los golpes limitados de metafonía, puede eliminarlos.

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

Algunos ajustes, y digamos alguna transcripción cirílica, y tendrás una solución bastante robusta.


2
Tenga en cuenta que soundex está especializado en inglés, existen otros algoritmos fonéticos para otros idiomas con diferentes reglas de pronunciación
Incógnito

8
Si bien esto es cierto, estamos en una situación extraña aquí. La solicitud principal fue "Estoy tratando de buscar la palabra Gadaffi", pero siento que la expresión regular era una pista falsa. No existe un libro de reglas sobre transliteración árabe-> latino, y como tal revertir una expresión regular de una lista no responderá completamente a la solicitud original.
tomwalsham

2
Creo que un sistema de coincidencia difusa es más adecuado, pero un algoritmo personalizado parece excesivo. El uso de un combo soundex-metaphone parece funcionar tan bien como la solución regex, lo que permite una mayor ortografía no anticipada mientras todavía se utilizan algos estándar.
Tomwalsham

El uso de metaphone2 y metaphone3 conduce a mejores resultados (es decir, casi todo en metaphone2 es KDF, mientras que metaphone1 no lo es del todo). Metaphone3 sin embargo, cuesta alrededor de 40 dólares.
Incógnito

27

Usando el módulo 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;

Esto produce la siguiente expresión regular:

(?-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

Creo que has terminado de complicar las cosas aquí. La expresión regular correcta es tan simple como:

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

Coincide con la concatenación de los siete puntos de código Unicode en árabe que forman la palabra القذافي (es decir, Gadaffi).


3
A continuación, simplemente canalice nytimes.com a través de Google Translate y Bob es su tío.
Robert Rossney el

19

Si desea evitar combinar cosas que nadie ha usado (es decir, evitar tender hacia ". +"), Su mejor enfoque sería crear una expresión regular que sea solo todas las alternativas (por ejemplo, (Qadafi | Kadafi | ...) ) luego compile eso en un DFA, y luego convierta el DFA nuevamente en una expresión regular. Asumiendo una implementación moderadamente sensata que le daría una expresión regular "comprimida" que garantiza que no contiene variantes inesperadas.


2
Sé que eso es posible allí, pero ¿cómo lo harías en la práctica (usando, por ejemplo, un lenguaje dinámico común)
Rory

3
Entiendo la teoría detrás de esto, pero al igual que @Rory, también estoy interesado en saber cómo lo harías en la práctica.
dancavallaro

Sí, pensé en hacerlo, para dar una mejor respuesta, pero estoy un poco ocupado en este momento. Tengo un código (feo y mal documentado) en code.google.com/p/lepl/source/browse/src/lepl/regexp/core.py que construye un dfa a partir de una expresión regular (en realidad, el analizador está en otra clase , pero el trabajo duro está ahí; vas regexp -> nfa -> dfa). pasar del dfa a un regexp es fácil (¿creo?).
Andrew Cooke

en realidad, la documentación allí es mejor de lo que recuerdo: o) la idea básica es que describas la expresión regular en términos de las clases cerca de la parte superior del archivo. que luego se puede traducir a una nfa con bastante facilidad (una nfa es realmente solo un conjunto de transiciones que dicen "si recibes esta carta, entonces puedes ir aquí o aquí ..." es bastante fácil de entender). el dfa es entonces una especie de versión "expandida" de la que se mantiene evitando tener que retroceder; eso es hecho por NfaToDfa (y es la parte difícil). el dfa puede considerarse como una expresión regular en sí misma que se escribe como conjuntos de caracteres muy complejos (?!)
andrew cooke

10

Si tienes una lista concreta de las 30 posibilidades, solo concatena todas con un grupo de "ors". Entonces puede estar seguro de que solo coincide con las cosas exactas que ha enumerado, y no más. Su motor RE probablemente podrá optimizar aún más y, bueno, con 30 opciones, incluso si no es así, no es un gran problema. Intentar jugar un poco con convertirlo manualmente en un RE "inteligente" no puede resultar mejor y puede resultar peor.


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)

Ciertamente no es la versión más optimizada, dividida en sílabas para maximizar las coincidencias mientras tratamos de asegurarnos de que no obtengamos falsos positivos.


7

Bueno, ya que estás haciendo coincidir palabras pequeñas, ¿por qué no pruebas un motor de búsqueda de similitud con la distancia de Levenshtein ? Puede permitir a lo sumo k inserciones o eliminaciones. De esta manera, puede cambiar la función de distancia a otras cosas que funcionen mejor para su problema específico. Hay muchas funciones disponibles en la biblioteca simMetrics.



1

¿Por qué no hacer un enfoque mixto? Algo entre una lista de todas las posibilidades y un Regex complicado que coincide demasiado.

Regex trata sobre la coincidencia de patrones y no puedo ver un patrón para todas las variantes en la lista. Al intentar hacerlo, también encontrará cosas como "Gazzafy" o "Quud'haffi", que probablemente no sean una variante usada y definitivamente no están en la lista.

Pero puedo ver patrones para algunas de las variantes, y así terminé con esto:

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

Al principio, enumero aquellos en los que no puedo ver un patrón, luego me siguen algunas variantes donde hay patrones.

Véalo aquí en www.rubular.com


Su \búnica se incluyen en el primero y las últimas alternativas.
Christopher Creutzig

1

Sé que esta es una vieja pregunta, pero ...

Ninguna de estas dos expresiones regulares es la más bonita, pero están optimizadas y ambas coinciden con TODAS las variaciones en la publicación original.

"Pequeña belleza" # 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)

"Pequeña belleza" # 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

Descansa en paz, Muammar.


0

Solo un apéndice: debe agregar "Gheddafi" como ortografía alternativa. Entonces el RE debería ser

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

0

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

En partes:

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

Nota: Solo quería darle una oportunidad a esto.


-1

¿Qué más comienza con Q, G o K, tiene ad, z o t en el medio y termina en "fi" que la gente realmente busca?

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

Hecho.

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

Interesante que me voten negativamente. ¿Alguien puede dejar algunos falsos positivos en los comentarios?


2
A partir de un diccionario de craqueo que resulta que han sentado en torno a: 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 . Sin embargo, algunos de esos no son falsos positivos.
BMDan

2
Y las adiciones a esa lista que resultan de terminar en [iy]lugar de solo i:gelatinify gentrify ghostlify giddify gladify goutify gratify "Gyula Dessewffy" katasrofy katastrofy khadafy quantify quasi-deify quizzify
BMDan
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.