Esto puede sonar como una pregunta estúpida, pero tuve una larga conversación con algunos de mis colegas desarrolladores y sonó como algo divertido de pensar.
Entonces; ¿Cuál es su pensamiento? ¿Cómo se ve un Regex, que nunca será igualado por ninguna cadena, nunca!
Editar : ¿Por qué quiero esto? Bueno, en primer lugar porque me parece interesante pensar en esa expresión y en segundo lugar porque lo necesito para un guión.
En ese script defino un diccionario como Dictionary<string, Regex>
. Esto contiene, como puede ver, una cadena y una expresión.
Basado en ese diccionario, creo métodos que todos usan este diccionario como referencia solamente sobre cómo deben hacer su trabajo, uno de ellos compara las expresiones regulares contra un archivo de registro analizado.
Si una expresión coincide, a otra Dictionary<string, long>
se le agrega un valor que devuelve la expresión. Entonces, para capturar cualquier mensaje de registro que no coincida con una expresión en el diccionario, creé un nuevo grupo llamado "desconocido".
A este grupo se agrega todo lo que no coincide con nada más. Pero para evitar que la expresión "desconocida" no coincida (por accidente) con un mensaje de registro, tuve que crear una expresión que ciertamente nunca coincide, sin importar la cadena que le dé.
Por lo tanto, ahí tienes mi razón para esta "no es una pregunta real" ...
fuente
Respuestas:
En realidad, esto es bastante simple,
aunque depende de la implementación / flags*:Coincidirá con un personaje
a
después del final de la cadena. Buena suerte.ADVERTENCIA:
Esta expresión es costosa: escaneará toda la línea, buscará el ancla de fin de línea y solo entonces no encontrará la
a
y devolverá una coincidencia negativa. (Vea el comentario a continuación para obtener más detalles).* Originalmente no pensé mucho en expresiones regulares en modo multilínea, donde
$
también coincide con el final de una línea. De hecho, coincidiría con la cadena vacía justo antes de la nueva línea , por lo que un carácter ordinario comoa
nunca puede aparecer después$
.fuente
$a
. Su equivalente en Perl$(?:a)
también es muy lentoperl -Mre=debug -e'$_=a x 50; /$(?:a)/'
.timeit
ypython3
.$a
coincidirá con el texto literal$a
, porque$
no es válido como un ancla en ese patrón.Apalancamiento
negative lookahead
:este RE es una contradicción en los términos y, por lo tanto, nunca coincidirá con nada.
NOTA:
En Python, re.match () agrega implícitamente un ancla de inicio de cadena (
\A
) al comienzo de la expresión regular. Este ancla es importante para el rendimiento: sin él, se escaneará toda la cadena. Aquellos que no usan Python querrán agregar el ancla explícitamente:fuente
(?=x)(?!x)
y así sucesivamente (concatenaciones de miradas contradictorias, y lo mismo para las miradas hacia atrás), y muchas de ellas también funcionan para valores arbitrarios dex
(las miradas hacia atrás necesitanx
s que coincidan con cadenas de longitud fija).r'a\bc'
probabilidades tendrá de encontrar una que funcione en todos los motores RE de interés): buscar un límite de palabras inmediatamente rodeado de letras en ambos lados (variante: caracteres sin palabras en ambos lados).perl -Mre=debug -e'$_=x x 8; /(?!x)x/'
. Puede hacerlo más rápido al anclarlo al principio\A(?!x)x
o al final(?!x)x\z
.perl -Mre=debug -e'$_=x x 8; /(?!x)x\z/; /\A(?!x)x/'
Uno que se perdió:
No puede coincidir porque la cadena vacía no contiene un límite de palabra. Probado en Python 2.5.
fuente
\`\b\'
funciona, lo que sustituye la sintaxis de Emacs por "principio / fin de texto" (en lugar de "principio / fin" desconectado").mira alrededor:
(?=a)b
Para los novatos de expresiones regulares: la mirada positiva hacia adelante
(?=a)
asegura que el siguiente carácter seaa
, pero no cambia la ubicación de búsqueda (ni incluye la 'a' en la cadena coincidente). Ahora que se confirma que el siguiente carácter esa
, la parte restante de la expresión regular (b
) coincide solo si el siguiente carácter lo esb
. Por lo tanto, esta expresión regular coincide solo si un personaje es ambosa
yb
al mismo tiempo.fuente
a\bc
, donde\b
es una expresión de ancho cero que coincide con el límite de la palabra.No puede aparecer en el medio de una palabra, a lo que lo forzamos.
fuente
a
en el texto.$.
.^
$.^
(?!)
fuente
^
solo tiene un significado especial como primer carácter de una$
expresión regular , y solo tiene un significado especial al final de una expresión regular, a menos que la expresión regular sea una expresión de varias líneas./$./
significa algo completamente diferente. Significa hacer coincidir el valor actual de$.
(número de línea de entrada) . Incluso/$(.)/
podría coincidir con algo si escribisteuse re '/s';
antes. (perl -E'say "\n" =~ /$(.)/s || 0'
)^
y$
sólo son especiales al principio y al final (respectivamente) del patrón, por lo que ninguno de$.
o.^
o$.^
funcionaría.(?!)
es una característica de Perl / PCRE, creo.Máxima correspondencia
Al menos uno
a
seguido de cualquier número dea
's, sin retroceder. Luego trata de hacer coincidir uno mása
.o Subexpresión independiente
Esto es equivalente a poner
a+
una subexpresión independiente, seguida de otraa
.fuente
Perl 5.10 admite palabras de control especiales llamadas "verbos", que están encerrados en
(*...)
secuencia. (Compárese con(?...)
una secuencia especial). Entre ellos, incluye el(*FAIL)
verbo que regresa de la expresión regular inmediatamente.Tenga en cuenta que los verbos también se implementan en PCRE poco después, por lo que puede usarlos en PHP u otros lenguajes usando la biblioteca PCRE también. (Sin embargo, no puedes en Python o Ruby. Usan su propio motor).
fuente
\b
coincide con los límites de las palabras: la posición entre una letra y una no letra (o el límite de la cadena).\B
es su complemento: coincide con la posición entre dos letras o entre no letras.Juntos no pueden igualar ninguna posición.
Ver también:
fuente
^\B\b
. En los idiomas en los que "comienzo de texto" y "comienzo de línea" tienen una sintaxis diferente, querrá usar la sintaxis "comienzo de texto", de lo contrario, probará cada línea. (por ejemplo, en Emacs esto sería\`\B\b
o"\\`\\B\\b"
.)^
es problemático en cierta sintaxis de expresión regular (por ejemplo, POSIX BRE) donde^
solo hay un ancla cuando es el primer carácter del patrón, y de lo contrario coincide con un^
carácter literal .:)
- esta es una pregunta no práctica, donde el objetivo era encontrar una respuesta interesante, no una respuesta eficiente. Dicho esto, el patrón se puede rechazar en el tiempo de línea (con el tamaño de la cadena de destino), por lo que no es malo para una expresión regular: la mayoría de los patrones aquí son iguales, e incluso^
podrían ser lineales si no están optimizados.Esto parece funcionar:
fuente
$.
. En ese caso, debe recurrir$(.)
ao más equivalente$(?:.)
.$.
coincidirá con un literal$
seguido de cualquier carácter, porque$
no es válido como un ancla en ese patrón.¿Qué
$^
tal o tal vez(?!)
?fuente
^
coincide con el inicio y$
el final de una línea.(?!)
: una anticipación negativa para una cadena vacía. Pero algunos sabores de expresiones regulares también lo tratarán como un error de sintaxis.$^
coincidirá con esos caracteres literales, porque los caracteres no son válidos como anclas (es decir, la razón por la que usó el patrón hace que no haga lo que deseaba)El más rápido será:
'a' puede ser cualquier carácter no especial ('x', 'y'). La implementación de Knio podría ser un poco más pura, pero esta será más rápida para todas las cadenas que no comiencen con el carácter que elija en lugar de 'a' porque no coincidirá después del primer carácter en lugar de después del segundo en esos casos.
fuente
^
es especial solo como primer personaje y de manera similar con$
. Con cualquier herramienta Unix, esa expresión regular coincidirá con cualquier cosa que contenga la cadena literala^
.>^
.Python no lo aceptará, pero Perl:
Esta expresión regular debería (en teoría) tratar de hacer coincidir un número infinito (par) de
w
s, porque el primer grupo (()
s) se repite en sí mismo. Perl no parece emitir ninguna advertencia, incluso debajouse strict; use warnings;
, por lo que supongo que es al menos válido, y mis pruebas (mínimas) no coinciden con nada, así que lo envío para su crítica.fuente
perl -Mre=debug -e'"www wwww wwwww wwwwww" =~ /(w\1w)/'
[^\d\D]
o(?=a)b
oa$a
oa^a
fuente
Esto no funcionará para Python y muchos otros lenguajes, pero en una expresión regular de Javascript,
[]
es una clase de caracteres válida que no se puede comparar. Entonces, lo siguiente debería fallar inmediatamente, sin importar la entrada:Me gusta más que
/$a/
porque, para mí, comunica claramente su intención. Y en cuanto a cuándo lo necesitaría, lo necesitaba porque necesitaba un respaldo para un patrón compilado dinámicamente basado en la entrada del usuario. Cuando el patrón no es válido, necesito reemplazarlo con un patrón que no coincida con nada. Simplificado, se ve así:fuente
Todos los ejemplos que involucran una coincidencia de límites siguen la misma receta. Receta:
Tome cualquiera de los comparadores de límites: ^, $, \ b, \ A, \ Z, \ z
Hacer lo contrario a lo que están destinados
Ejemplos:
^ y \ A están destinados al principio, así que no los use al principio
\ b coincide con un límite de palabra, así que úselo entre
$, \ Z y \ z están destinados al final, así que no los uses al final
Otros implican el uso de lookahead y lookbehind, que también funcionan con la misma analogía: si da un lookahead positivo o negativo seguido de algo opuesto
Si das una mirada positiva o negativa detrás de algo opuesto
Podrían existir más patrones y más analogías.
fuente
¡Tantas buenas respuestas!
Similar a la respuesta de @ nivk, me gustaría compartir la comparación de rendimiento de Perl para diferentes variantes de expresiones regulares que nunca coinciden.
Velocidad de expresión regular:
Velocidad de expresión regular:
(Ubuntu en Intel i5-3320M, Linux kernel 4.13, Perl 5.26)
fuente
Yo creo eso
cubre incluso los casos en los que la expresión regular incluye marcas como MULTILINE, DOTALL, etc.
Creo (pero no lo he comparado) que cualquiera que sea la longitud (> 0) de la cadena entre
\Z
y\A
, el tiempo de falla debe ser constante.fuente
o
Con PCRE y PERL puede usar este verbo de control de retroceso que obliga al patrón a fallar inmediatamente.
fuente
Después de ver algunas de estas excelentes respuestas, el comentario de @arantius (con respecto al tiempo
$x
vsx^
vs(?!x)x
) sobre la respuesta actualmente aceptada me hizo querer cronometrar algunas de las soluciones dadas hasta ahora.Usando el estándar de línea de 275k de @ arantius, ejecuté las siguientes pruebas en Python (v3.5.2, IPython 6.2.1).
TL; DR:
'x^'
y'x\by'
son los más rápidos por un factor de al menos ~ 16, y contrario al hallazgo de @ arantius,(?!x)x
fue uno de los más lentos (~ 37 veces más lento). Entonces, la cuestión de la velocidad ciertamente depende de la implementación. Pruébelo usted mismo en su sistema previsto antes de confirmar si la velocidad es importante para usted.ACTUALIZACIÓN: Al parecer, existe una gran discrepancia entre el tiempo
'x^'
y'a^'
. Consulte esta pregunta para obtener más información y la edición anterior para los tiempos más lentos con ena
lugar dex
.La primera vez que ejecuté esto, olvidé
r
mostrar las últimas 3 expresiones, por lo que'\b'
se interpretó como'\x08'
el carácter de retroceso. Sin embargo, para mi sorpresa, ¡'a\x08c'
fue más rápido que el resultado más rápido anterior! Para ser justos, aún coincidirá con ese texto, pero pensé que todavía valía la pena señalarlo porque no estoy seguro de por qué es más rápido.Mi archivo de prueba fue creado usando una fórmula para "... Contenido legible y sin líneas duplicadas" (en Ubuntu 16.04):
fuente
\B\b
tiene un rendimiento terriblemente defectuoso (como todos los patrones que no están anclados a una posición, pero este patrón es particularmente malo). Intenta hacer benchmarking en su^\B\b
lugar.Expresiones regulares vacías
La mejor expresión regular para que nunca coincida con nada es una expresión regular vacía. Pero no estoy seguro de que todo el motor de expresiones regulares lo acepte.
Regex imposible
La otra solución es crear una expresión regular imposible. Descubrí que
$-^
solo toma dos pasos para calcular, independientemente del tamaño de su texto ( https://regex101.com/r/yjcs1Z/1 ).Para referencia:
$^
y$.
tome 36 pasos para calcular -> O (1)\b\B
toma 1507 pasos en mi muestra y aumenta con el número de caracteres en su cadena -> O (n)Tema más popular sobre esta pregunta:
fuente
¿Tal vez esto?
fuente
re.compile('$.+^', re.MULTILINE|re.DOTALL).search('a\nb\nc\n')
devuelve un objeto de coincidencia correspondiente a byc (y todas las líneas nuevas adyacentes y entre ellas). El enfoque de anticipación negativa que recomiendo funciona (es decir, no coincide con nada) para cualquier combinación de indicadores con los que podría compilarse.$
y^
./\z.+\A/
(ver perldoc perlre ). Eso evita que el modo de varias líneas y una sola línea (use re '/ms'
) lo afecte.y reemplace ... con todos los símbolos imprimibles;). Eso es para un archivo de texto.
fuente
[^\x00-\xFF]+
(para implementaciones basadas en bytes).[^\s\S]
. Pero como ya dijo Ferdinand Beyer, coincidiría con una cadena vacía.*
; déjalo apagado o reemplázalo con+
, y tiene que coincidir con al menos un personaje. Si la clase excluye todos los caracteres posibles, no puede coincidir con nada.¿Qué pasa en lugar de expresiones regulares, solo use una declaración if falsa? En javascript:
fuente
Una solución portátil que no dependerá de la implementación de regexp es usar una cadena constante que está seguro de que nunca aparecerá en los mensajes de registro. Por ejemplo, haga una cadena basada en lo siguiente:
Claro, este no es un desafío intelectual, sino más bien una programación de cinta adhesiva .
fuente
Crea un patrón que solo contiene caracteres alfanuméricos y '
-
' (ninguno de los cuales son caracteres especiales de expresiones regulares), pero es estadísticamente imposible que la misma cadena haya aparecido en algún lugar antes (porque ese es el objetivo de un GUID).fuente