La expresión regex negativa negativa no es válida en JavaScript
regex-lookarounds (2)
Aquí hay una manera de analizar cadenas HTML usando DOM en JS y realizar reemplazos solo fuera de las etiquetas:
var s = ''<span class="css">55</span> 2 >= 1 2 > 1'';
var doc = document.createDocumentFragment();
var wrapper = document.createElement(''myelt'');
wrapper.innerHTML = s;
doc.appendChild( wrapper );
function textNodesUnder(el){
var n, walk=document.createTreeWalker(el,NodeFilter.SHOW_TEXT,null,false);
while(n=walk.nextNode())
{
if (n.parentNode.nodeName.toLowerCase() === ''myelt'')
n.nodeValue = n.nodeValue.replace(/>=?/g, "EQUAL");
}
return el.firstChild.innerHTML;
}
var res = textNodesUnder(doc);
console.log(res);
alert(res);
Esta pregunta ya tiene una respuesta aquí:
- Javascript: ¿equivalente de lookbehind negativo? 13 respuestas
Considerar:
var re = /(?<=foo)bar/gi;
Es una expresión regular no válida en Plunker. ¿Por qué?
JavaScript carece de soporte para
lookbehinds
hacia
lookbehinds
como
(?<=…)
(positivo) y
(?<!…)
(negativo), pero eso no significa que aún no pueda implementar este tipo de lógica en JavaScript.
Coincidencia (no global)
Partido positivo de lookbehind:
// from /(?<=foo)bar/i
var matcher = mystring.match( /foo(bar)/i );
if (matcher) {
// do stuff with matcher[1] which is the part that matches "bar"
}
Ancho fijo de lookbehind negativo:
// from /(?<!foo)bar/i
var matcher = mystring.match( /(?!foo)(?:^.{0,2}|.{3})(bar)/i );
if (matcher) {
// do stuff with matcher[1] ("bar"), knowing that it does not follow "foo"
}
Las retrospectivas negativas se pueden hacer sin la bandera global, pero solo con un ancho fijo, y debe calcular ese ancho (que puede ser difícil con las
alternations
).
Usar
(?!foo).{3}(bar)
sería más simple y más o menos equivalente, pero desde entonces no coincidirá con una línea que comience con "armadura"
.
no puede coincidir con las nuevas líneas, por lo que necesitamos la alternancia del código anterior para que coincida con las líneas con "barra" antes del carácter cuatro.
Si lo necesita con un ancho variable, use la siguiente solución global y ponga un
break
al final de la estrofa
if
.
(Esta limitación es bastante común.
.NET
,
vim
y
JGsoft
son los
only
motores de
JGsoft
regulares que admiten ancho de retrospectiva variable.
PCRE
,
PHP
y
Perl
están limitados a ancho fijo.
Python
requiere un
módulo de expresiones regulares alternativo
para admitir esto. Dicho esto, la lógica de la solución a continuación debería funcionar para todos los idiomas que admiten expresiones regulares).
Coincidencia (global)
Cuando necesita hacer un bucle en cada coincidencia en una cadena dada (el modificador
g
, coincidencia global), debe redefinir la variable de
matcher
en cada iteración del bucle y debe usar
RegExp.exec()
(con el RegExp creado
antes del bucle
) ¡porque
String.match()
interpreta el modificador global de manera
differently
y creará un bucle infinito!
Mirada positiva global detrás:
var re = /foo(bar)/gi; // from /(?<=foo)bar/gi
while ( matcher = re.exec(mystring) ) {
// do stuff with matcher[1] which is the part that matches "bar"
}
"Cosas", por supuesto, puede incluir rellenar una matriz para su uso posterior.
Mirada negativa global:
var re = /(foo)?bar/gi; // from /(?<!foo)bar/gi
while ( matcher = re.exec(mystring) ) {
if (!matcher[1]) {
// do stuff with matcher[0] ("bar"), knowing that it does not follow "foo"
}
}
Tenga en cuenta que hay
cases
en los que esto no representará completamente la mirada negativa hacia atrás.
Considere
/(?<!ba)ll/g
haciendo coincidir contra
Fall ball bill balll llama
.
Encontrará solo tres de los cuatro partidos deseados porque cuando analiza
balll
, encuentra la
ball
y luego continúa un personaje tarde en
l llama
.
Esto solo ocurre cuando una coincidencia parcial al final podría interferir con una coincidencia parcial en un extremo diferente (
balll
breaks
(ba)?ll
pero
foobarbar
está bien con
(foo)?bar
) La única solución para esto es usar el fijo anterior método de ancho.
Sustitución
Hay un maravilloso artículo llamado
Mimicking Lookbehind en JavaScript
que describe cómo hacer esto.
Incluso tiene un seguimiento que apunta a una
colección de funciones cortas
que implementan esto en JS.
Implementar lookbehind en
String.replace()
es mucho más fácil ya que puede crear una
función anónima
como reemplazo y manejar la lógica de lookbehind en esa función.
Estos funcionan en la primera coincidencia, pero pueden hacerse globales simplemente agregando el modificador
g
.
Reemplazo positivo de lookbehind:
// assuming you wanted mystring.replace(/(?<=foo)bar/i, "baz"):
mystring = mystring.replace( /(foo)?bar/i,
function ($0, $1) { return ($1 ? $1 + "baz" : $0) }
);
Esto toma la cadena de destino y reemplaza las instancias de
bar
con
baz
siempre que sigan a
foo
.
Si lo hacen,
$1
coincide y el operador ternario (
?:
Devuelve el texto coincidente y el texto de reemplazo (pero no la parte de la
bar
).
De lo contrario, el operador ternario devuelve el texto original.
Reemplazo negativo de lookbehind:
// assuming you wanted mystring.replace(/(?<!foo)bar/i, "baz"):
mystring = mystring.replace( /(foo)?bar/i,
function ($0, $1) { return ($1 ? $0 : "baz") }
);
Esto es esencialmente lo mismo, pero dado que es una mirada negativa hacia atrás, actúa cuando falta
$1
(no necesitamos decir
$1 + "baz"
aquí porque sabemos que
$1
está vacío).
Esto tiene la misma advertencia que la otra solución de aspecto negativo de ancho dinámico detrás y se soluciona de manera similar mediante el uso del método de ancho fijo.