validator regulares regular one expresiones examples ruby regex

ruby - regulares - gsub parcial reemplazar



ruby regex validator (2)

Me gustaría reemplazar solo el grupo entre paréntesis en esta expresión:

my_string.gsub(/<--MARKER_START-->(.)*<--MARKER_END-->/, ''replace_text'')

para obtener: <--MARKER_START-->replace_text<--MARKER_END-->

Sé que podría repetir los MARKER_START completos MARKER_START y MARKER_END en la expresión de sustitución, pero pensé que debería haber una forma más simple de hacerlo.


Podrías hacer algo como esto:

my_string.gsub(/(<--MARKER_START-->)(.*)(<--MARKER_END-->)/, ''/1replace_text/3'')


Puede hacerlo con aserciones de look-ahead y look-ahead de ancho cero .

Esta expresión regular debería funcionar en ruby ​​1.9 y en perl y en muchos otros lugares:

Nota: ruby ​​1.8 solo admite aserciones de anticipación. Necesita tanto mirar hacia adelante como hacia atrás para hacer esto correctamente.

s.gsub( /(?<=<--MARKER START-->).*?(?=<--MARKER END-->)/, ''replacement text'' )

Lo que sucede en ruby ​​1.8 es que ?<= Hace que se bloquee porque no comprende la afirmación de mirar hacia atrás. Para esa parte, debes recurrir a la retro-referencia, como menciona Greig Hewgill

entonces lo que obtienes es

s.gsub( /(<--MARKER START-->).*?(?=<--MARKER END-->)/, ''/1replacement text'' )

EXPLICACIÓN EL PRIMERO:

He reemplazado el (.)* En medio de tu expresión regular con .*? - Esto no es codicioso. Si no tienes codicia, tu expresión regular intentará hacer coincidir todo lo que pueda: si tienes 2 marcadores en una línea, sale mal. Esto se ilustra mejor con el ejemplo:

"<b>One</b> Two <b>Three</b>".gsub( /<b>.*<//b>/, ''BOLD'' ) => "BOLD"

Lo que realmente queremos:

"<b>One</b> Two <b>Three</b>".gsub( /<b>.*?<//b>/, ''BOLD'' ) => "BOLD Two BOLD"

EXPLICACIÓN EL SEGUNDO:

zero-width-look-ahead-assertion suena como una pila gigante de confusión nerdly.

Lo que realmente significa "afirmación de anticipación" es "coincidencia única, si lo que estamos buscando es seguido por este otro material".

Por ejemplo, solo haga coincidir un dígito, si es seguido por un F.

"123F" =~ //d(?=F)/ # will match the 3, but not the 1 or the 2

Lo que realmente significa "ancho cero" es "considerar el ''seguido de'' en nuestra búsqueda, pero no lo cuente como parte de la coincidencia al hacer reemplazo o agrupación o cosas por el estilo. Usando el mismo ejemplo de 123F, si no lo hicimos No use la aserción de búsqueda anticipada, y en su lugar solo haga esto:

"123F" =~ //dF/ # will match 3F, because F is considered part of the match

Como puede ver, esto es ideal para verificar nuestro <--MARKER END--> , pero lo que necesitamos para <--MARKER START--> es la capacidad de decir "Only match, si lo que estamos buscando" para SIGUE esta otra cosa ". Eso se llama una afirmación de mirar hacia atrás, que ruby ​​1.8 no tiene por alguna extraña razón ...

Espero que tenga sentido :-)

PD: ¿Por qué utilizar aserciones de búsqueda anticipada en lugar de solo referencias retrospectivas? Si usa la búsqueda anticipada, en realidad no está reemplazando los <--MARKER--> bits, solo los contenidos. Si usa referencias retrospectivas, está reemplazando todo el lote. No sé si esto tiene un gran impacto en el rendimiento, pero desde el punto de vista de la programación parece ser lo correcto, ya que no queremos reemplazar los marcadores en absoluto.