2012-09-19 20 views
7

tengo la siguiente cadena:Regex reemplazar texto pero excluyen el texto se vea entre etiqueta específica

Lorem ipsum Test dolor sit amet, consetetur sadipscing elitr, sed diam nonumy <a href="http://Test.com/url">Test</a> eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd sed Test dolores et ea rebum. Stet clita kasd gubergren, no sea <a href="http://url.com">Test xyz</a> takimata sanctus est Lorem ipsum dolor sit amet. 

Ahora me reemplazar la cadena fuera de las etiquetas de un no entre las etiquetas (por ejemplo, sustituidos con '1234' 'prueba')

Lorem ipsum 1234 dolor sit amet, consetetur sadipscing elitr, sed diam nonumy <a href="http://Test.com/url">Test</a> eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd sed 1234 dolores et ea rebum. Stet clita kasd gubergren, no sea <a href="http://url.com">Test xyz</a> takimata sanctus est Lorem ipsum dolor sit amet. 

empecé con esta expresión regular: (?!<a[^>]*>)(Test)([^<])(?!</a>)

Sin embargo, dos problemas no se resuelven:

  1. El texto de 'Prueba' se sustituyó también dentro de las etiquetas (por ejemplo)
  2. dice el texto entre la etiqueta no coincide exactamente con el texto buscado, también se reemplazará (por ejemplo, <a href="http://url">Test xyz</a>)

Espero que alguien tenga una solución para resolver este problema.

Respuesta

9
(?!<a[^>]*?>)(Test)(?![^<]*?</a>) 

mismo que zb226, pero optimizado con un partido flojo

Además, el uso de expresiones regulares en HTML puro es no recomendado.

+0

También añadió la bandera \ b para que coincida con un límite de palabra: (?!? ] *>) (\ b BTest \) (?! [^ <]*?) – Weri

+0

Eso debería dar más al optimizador de expresiones regex para trabajar. Tampoco debería afectar negativamente sus coincidencias, siempre que '_Test_, _Test, o Test_' no estén en su documento (y suponiendo que no le importaría hacerlas coincidir si lo fueran). – protist

+0

El lookaheaed antes de Test y el partido perezoso no tienen sentido. Ver mi respuesta – Adam

3

Esto debería hacer el truco:

(?!<a[^>]*>)(Test)(?![^<]*</a>) 

Pruebe usted mismo on regexr.

2

Resucitando esta antigua pregunta porque tenía una solución simple que no se mencionaba.

Con todos los descargos de responsabilidad sobre el uso de expresiones regulares para analizar html, aquí hay una manera simple de hacerlo.

Método para Perl/PCRE

<a[^>]*>[^<]*<\/a(*SKIP)(*F)|Test 

demo

Solución general

<a[^>]*>[^<]*<\/a|(Test) 

En esta versión, el texto que desea reemplazar es capturado en el Grupo 1 y el el reemplazo se realiza mediante una simple devolución de llamada o lambda.

demo

Referencia

  1. How to match pattern except in situations s1, s2, s3
  2. Para la implementación del código ver los ejemplos de código en How to match a pattern unless...
+0

La parte más importante para mí era saber '$ reemplazado = preg_replace_callback ( \t $ expresiones regulares, \t función ($ m) {if (empty ($ m [1])) return $ m [0]; \t \t \t \t \t else return "Superman";}, \t $ subject); '. Entonces necesito devolver 'm [0]' si 'm [1]' está vacío. Realmente es bueno saber ¡Gracias! – mgutt

4

No tiene sentido poner un símbolo de anticipación antes del partido.Así que la siguiente es equivalente a protista respuesta:

(Test)(?![^<]*?</a>) 

también desde < no está permitido el partido perezoso ? es superflua, por lo que también es equivalente a

(Test)(?![^<]*</a>) 

Esto selecciona todos Test que no son seguidos por un </a> sin el símbolo < en el medio. Esta es la razón por la cual la prueba que aparece antes o después de cualquier <a ...> .. </a> será reemplazada.

Sin embargo, tenga en cuenta que

Lorem Test dolor <a href="http://Test.com/url">Test <strong>dolor</strong></a> eirmod 

sería cambiado a

Lorem 1234 dolor <a href="http://1234.com/url">1234 <strong>dolor</strong></a> eirmod 

Con el fin de atrapar que podría cambiar su expresión regular para

(Test)(?!(.(?!<a))*?</a>) 

el que hace lo siguiente:

Seleccione cada palabra Test que no va seguida de una cadena ***</a> donde a cada carácter en *** no le sigue *** seguido de <a.

Tenga en cuenta que aquí el partido perezoso ? tiene sentido.

protista dijo

Además, el uso no se recomienda expresiones regulares en HTML puro.

Estoy de acuerdo con eso. Un problema es que podría causar problemas si una etiqueta no está cerrada o abierta. Por ejemplo, todas las soluciones mencionadas aquí cambiarían

Lorem Test dolor Test <strong>dolor</strong></a> eirmod 

a

Lorem Test dolor Test <strong>dolor</strong></a> eirmod 1234 dolores sea 1234 takimata 
Cuestiones relacionadas