Convierta la etiqueta de cierre de PHP en comentario

149

Una de las líneas en mi script contiene una etiqueta de cierre de PHP dentro de una cadena. Bajo operación normal esto no causa un problema, pero necesito comentar la línea.

He intentado crear un comentario en esta línea con //, /* */y #sin embargo ninguno de ellos el trabajo, el analizador considera etiqueta de cierre para ser una etiqueta de cierre real.

Aquí está la línea en cuestión:

$string = preg_replace('#<br\s*/?>(?:\s*<br\s*/?>)+#i', '<br />', $string);
//                              ^^             ^^

¿Qué puedo hacer para comentar la línea anterior?

v1n_vampire
fuente
18
Gracioso problema, pero real. Yo voto
Voitcus
17
DIOS MIO. Al principio era escéptico de su pregunta, listo para preguntar cuál era el problema, pero luego traté de comentar una línea con una cadena que contenía '?>' Y lo obtuve. Esto debería agregarse a la larga lista de phpsadness.com
lolesque
66
La utilidad de tal "característica" se explica en php.net/manual/en/language.basic-syntax.comments.php , es útil en el caso de una sola línea <?php # echo 'simple';?>.
lolesque
2
@lolesque Gracias por ese enlace. Una buena. Uno relacionado que también cubre otros idiomas: wiki.theory.org/YourLanguageSucks
Simon Forsberg
55
@ OndraŽižka todo lo que está haciendo es eliminar repetidas etiquetas br. una expresión regular funciona bien para eso. Solo porque sea malo a veces no significa que sea malo todo el tiempo.
Kip

Respuestas:

124

Usa un truco: concatenar la cuerda de dos piezas. De esta manera, la etiqueta de cierre se corta en dos, y ya no es una etiqueta de cierre válida.'?>' --> '?'.'>'

En su código:

$string = preg_replace('#<br\s*/?'.'>(?:\s*<br\s*/?'.'>)+#i', '<br />', $string);

Esto hará que los //comentarios funcionen.

Para que los /* */comentarios funcionen, también deberías dividir la */secuencia:

$string = preg_replace('#<br\s*'.'/?'.'>(?:\s*<br\s*'.'/?'.'>)+#i', '<br />', $string);

Recuerde, a veces, aunque el todo es más que la suma de sus partes, pero ser codicioso es malo, hay veces que es mejor quedarse con menos . :)

ppeterka
fuente
@ppeterka Wow, ni siquiera pensé en eso. Gracias.
v1n_vampire
1
Tuve que usar este truco en C hace 2 días para una cadena que contiene??<
Ryan Amos
2
Muy buena. ¿Por qué nunca pienso de esa manera?
San
73

La forma más fácil

Cree una variable separada para mantener su expresión regular; de esta manera puedes simplemente comentar la preg_replace()declaración:

$re = '#<br\s*/?>(?:\s*<br\s*/?>)+#i';
// $string = preg_replace($re, '<br />', $string);

Arreglar usando clases de caracteres

Para corregir los comentarios de línea, puede romper ?>colocando >dentro de una clase de caracteres de esta manera:

$string = preg_replace('#<br\s*/?[>](?:\s*<br\s*/?[>])+#i', '<br />', $string);
                                 ^ ^              ^ ^

Para corregir los comentarios de bloque, puede aplicarlo a /:

$string = preg_replace('#<br\s*[/]?>(?:\s*<br\s*[/]?>)+#i', '<br />', $string);
                               ^ ^              ^ ^

Para arreglar ambos estilos de comentarios, puede poner / y > en su propia clase de caracteres.

Arreglar usando el /xmodificador

El x modificador , también conocido como PCRE_EXTENDED, ignora espacios y líneas nuevas en una expresión regular (excepto cuando ocurren dentro de una clase de caracteres); Esto permite agregar espacios para separar los caracteres problemáticos. Para arreglar ambos estilos de comentario:

$string = preg_replace('#<br\s* /? >(?:\s*<br\s* /? >)+#ix', '<br />', $string);
                               ^  ^             ^  ^
Jack
fuente
@Cthulhu +1 (y para la respuesta también, por supuesto). Además (al menos para mí) esto hace que la expresión regular sea un poco más difícil de entender. No mucho, pero si viera esta expresión regular, diría: Hmmm, ¿qué está pasando? Pero eso es francamente y totalmente subjetivo.
ppeterka
1
@ppeterka Estoy de acuerdo, así que encontré otra forma, usando el xmodificador :)
Ja --ck
@ Jack Nice, le daría otro +1 por ello, he aprendido algo nuevo ... Me olvido de los modificadores de expresiones regulares (rara vez los uso aparte g) ...
ppeterka
@ Jack Gracias, aprendo cosas nuevas sobre expresiones regulares de la solución.
v1n_vampire
1
+1 para separar la expresión regular en una línea anterior. Mantiene la expresión regular igual, pero aún permite que se comente la lógica.
38

Por qué tus intentos no funcionaron:

// $string = preg_replace('#<br\s*/?>(?:\s*<br\s*/?>)+#i',...
                                   ^ doesn't work due to ?> ending php

/* $string = preg_replace('#<br\s*/?>(?:\s*<br\s*/?>)+#i',... */
                                 ^ doesn't work due to */ closing comment

Que funciona:

/* $string = preg_replace('#<br\s*[/]?>(?:\s*<br\s*[/]?>)+#i',... */
                                  ^ ^              ^ ^
// $string = preg_replace('#<br\s*/?[>](?:\s*<br\s*/?[>])+#i',...
                                    ^ ^              ^ ^

Más lejos...

Después de lo anterior, debería poder usar /*para comentar la línea. Si deja ?>intacto, //no puede comentar una línea completa. El siguiente texto ?>podría ser html, que está fuera del control del intérprete PHP, por lo que no funcionaría.

De la documentación:

Los estilos de comentario de "una línea" solo comentan al final de la línea o al bloque actual de código PHP, lo que ocurra primero. Esto significa que el código HTML después de // ...?> O # ...?> Se imprimirá:?> Sale del modo PHP y vuelve al modo HTML, y // o # no pueden influir en eso.

Anirudh Ramanathan
fuente
Gracias, tantas cosas que aún no sé ... Es útil.
v1n_vampire
44
Esta publicación merecería muchos más +1 ... Solo por la explicación detallada.
ppeterka
15

Otra idea: escapar de la >(y la /, si desea utilizar un /*...*/comentario):

$string = preg_replace('#<br\s*\/?\>(?:\s*<br\s*\/?\>)+#i', '<br />', $string);

El motor de expresiones regulares ignora un escape "innecesario", pero es útil en este caso (por las razones descritas en las otras respuestas).

Tim Pietzcker
fuente
@ppeterka: Utilicé una barra invertida en lugar de una clase de personaje (pero sí, me
perdí
Lo siento, parece que estoy cansado ... Me di cuenta de la segunda, que quedó allí rodeada de [] ...
ppeterka
10

¿Por qué utilizar "trucos" complicados y difíciles de leer para solucionar el problema?

? es solo un atajo cuantificador por conveniencia, así que

Simplemente use la versión larga del cuantificador{0,1} , significa "mínimo 0 máximo 1 ocurrencia":

$string = preg_replace('#<br\s*/{0,1}>(?:\s*<br\s*/{0,1}>)+#i', '<br />', $string);
Stema
fuente
1
+1 esta página comienza a ser un muy buen lugar para reunir trucos de expresiones regulares para mantener en el fondo de nuestras mentes.
ppeterka
1
@ppeterka, en realidad llamaría a todas las otras respuestas "trucos", pero mi respuesta es simplemente usar la versión larga del cuantificador y no el atajo.
Stema
3
Sin ofender, solo eso en mi diccionario, usar la versión larga de una expresión en lugar del azúcar sintáctico más corto y conveniente que uno cuenta como un truco también ...
ppeterka
8

Algunas otras formas que vale la pena agregar al libro de trucos RegEx :

Primero, puede compactar su RegEx para: /(<br\s*/?>)+/iy reemplazarlo <br />(sin necesidad de cargar el RegExP con lookaheads) y siempre terminará con el salto de línea XHMTL elegido.

Otras formas de modificar su RegEx para que no active el */comentario ?>final o el script final:

  • Use cuantificadores posesivos : lo #(<br\s*+/?+>)+#ique básicamente significa que \s*+si encuentra espacios en blanco, coincida con tantos como existen y manténgalo, y /?+si encuentra una barra oblicua, ¡manténgalo!
  • Adjuntar \s*y /*en grupos de captura =>#(<br(\s*)(/?)>)+#i

Demos en vivo: http://codepad.viper-7.com/YjqUbi

Y dado que apoyamos el comportamiento posesivo, el RegEx más rápido que también evita el problema de los comentarios es: demostración explicada#(<br\s*+/?+>)++#i


En cuanto a comentar en situaciones difíciles

Cuando no puede cambiar el código, o ya ha utilizado un comentario de varias líneas y:

1. Use un nowdoc :

    $string='Hello<br>World<br><br />World<br><br><br>Word!';
    <<<'comment'
    $string = preg_replace('#(<br\s*/?>)+#i', '<br />', $string);
comment;

Código en vivo: http://codepad.viper-7.com/22uOtV

Nota: un nowdoc es similar a un heredoc pero no analiza el contenido y debe tener su delimitador inicial entre 'comillas simples '( tenga en cuenta que el delimitador final no puede ser ideado , ¡debe ir seguido de ;una nueva línea ! )

2. Salta el código con un goto :

$string='Hello<br>World<br><br />World<br><br><br>Word!';
goto landing;
$string = preg_replace('#(<br\s*/?>)+#i', '<br />', $string);
landing:

Ejemplo en vivo: http://codepad.viper-7.com/UfqrIQ

3. Salta sobre el código con if(false)o if(0):

$string='Hello<br>World<br><br />World<br><br><br>Word!';
if(0){
$string = preg_replace('#(<br\s*/?>)+#i', '<br />', $string);
}

Prueba: http://codepad.viper-7.com/wDg5H5

CSᵠ
fuente