javascript - standard - html spec
¿Hay un caso donde "[^ xy]" no es igual a "(?! X | y)."? (5)
Estoy trabajando en mi propia biblioteca de JavaScript para admitir nuevos metacaracteres y funciones para expresiones regulares, y me gustaría encontrar un caso donde [^xy]
no sea equivalente a (?!x).
(o más específicamente (?:(?!x|y).)
).
Toma el texto de ejemplo: "abc/n"
Digamos que quiero emular una expresión regular de Perl: //A.{3}/Z/s
Con el indicador de línea simple, la expresión regular de JavaScript debe ser equivalente a: /^[/s/S]{3}/n*$(?!/s)/
( /A
convierte en ^
/A
convierte en [/s/S]
, /Z
convierte en /n*$(?!/s)
)
Ahora, /^.{3}$/
fallaría, pero /^[/s/S]{3}/n*$(?!/s)/
capturaría "abcabc" (igual que la expresión regular de Perl)
Como /Z
contiene más que solo un metacarácter, emular [^/Z]
parece ser más difícil.
Tome el texto de ejemplo: "abcabc/n"
La propuesta de expresión regular de JavaScript para Perl regex /.{3}[^/Za]/g
sería .{3}(?:(?!/n*$(?!/s)|a).)/g
Ambos coincidirán con "bcab"
Así que, finalmente, vuelvo a plantear la pregunta. ¿Existe un caso en el que [^xy]
no sea equivalente a (?:(?!x|y).)
Con ese escenario, tal vez en una expresión regular más compleja donde un lookahead cambiaría el escenario?
¿Hay algún caso en el que
[^xy]
no sea igual a(?!x|y).
?
Solo el que ya ha descrito: el punto JS no coincide con las líneas nuevas y debe reemplazarse con [/s/S]
.
/Z
convierte en/n$(?!/s)
Eso se ve mal. Después del final de la cadena ( /z
/ $
) nunca habrá nada, independientemente de si hay espacios en blanco o no. Afaik, /Z
es una aserción de ancho cero (no consume las nuevas líneas) y debe ser equivalente a
(?=/n*$)
// ^ not sure whether ? or *
Como
/Z
contiene más que solo un metacarácter, emular[^/Z]
parece ser más difícil.
¿Qué quieres decir con "metacarácter"? Es una aserción de ancho cero, y no tiene mucho sentido en una clase de personaje. Supongo que es un error de sintaxis o se interpretará literalmente (sin escapar) como [^Z]
.
Como dijeron los demás, debes usar [/s/S]
lugar de .
En el reemplazo. De lo contrario, si está haciendo esa transformación solo a través de las cadenas literales, hay algunas cosas más que cuidar. En particular, los meta caracteres y las secuencias de escape:
[^*)] => (?!/*|/))[/s/S]
Pero supongo que tendrás que ocuparte del análisis y la escritura de los metacaracteres de todos modos.
Sin embargo, el más complicado es probablemente /b
, porque es un carácter (retroceso) en las clases de caracteres y un límite de palabra fuera. Así que en el reemplazo, tendrías que ir con un escape octal o hexadecimal:
[^a/b] => (?!a|/10)[/s/S]
or => (?!a|/x08)[/s/S]
Aparte de eso, los dos siempre deben ser equivalentes.
Para la cadena de entrada "x/na"
, las 2 expresiones regulares dan diferentes salidas, porque .
no coincide con las nuevas líneas.
console.log("x/na".match(/(?:(?!x|y).)/))
["a", index: 2, input: "x↵a"]
console.log("x/na".match(/[^xy]/))
["↵", index: 1, input: "x↵a"]
Si cambias .
para [/s/S]
, la salida es idéntica en este caso:
console.log("x/na".match(/(?:(?!x|y)[/s/S])/))
["↵", index: 1, input: "x↵a"]
No puedo pensar en ningún otro caso en este momento.
Un caso donde el formato [^xy]
no es el mismo que (?:(?!x|y).)
Sería donde x fue una aserción de ancho cero en lugar de un carácter real como:
Dado este texto de muestra: ab-yz
Regex: [^/by]
Ejemplo: http://www.rubular.com/r/ERKrqyeAs9
Devoluciones:
[0] => a
[1] => b
[2] => -
[3] => z
Mientras
Regex: (?:(?!/b|y).)
Ejemplo: http://www.rubular.com/r/V5RdyQEQo5
Devoluciones:
[0] => b
[1] => z
Otras expresiones no equivalentes, se enfocan principalmente en el hecho de que la misma sintaxis tiene diferentes elementos dentro o fuera de la clase de caracteres:
-
[^^y]
produce a, b, -, z no es igual a(?:(?!^|y).)
produce b, -, z -
[^.y]
produce a, b, -, z no es igual a(?:(?!.|y).)
no produce nada
O puedes intentar esto en un nugget Unicode en Perl: http://ideone.com/2xMfkQ
print "/ncapture/n";
@m = ("ss" =~ m/^(?:(?!/xDF|y).)+$/ui );
print for @m;
print "/nclass/n";
@m = ("ss" =~ m/^[^/xDFy]+$/ui) ;
print for @m;
Rendimientos:
capture
class
1
[^xy]
coincidirá con /n
. (?!x|y).
no coincidirá con /n
por defecto (porque .
no coincide con /n
)
No creo que javascript tenga un modificador "dotall" o "single-line", pero con nuevas versiones de cada navegador cada dos meses, he perdido la pista.