web-dev-qa-db-fra.com

Convertir PHP balise de fermeture en commentaire

L'une des lignes de mon script contient une balise de fermeture PHP à l'intérieur d'une chaîne. En fonctionnement normal, cela ne pose pas de problème, mais je dois commenter la ligne.

J'ai essayé de commenter cette ligne avec //, /**/ et # mais aucun d'entre eux ne fonctionne, l'analyseur considère que la balise de fermeture est une balise de fermeture réelle.

Voici la ligne en question:

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

Que puis-je faire pour commenter la ligne ci-dessus?

150
v1n_vampire

Utilisez une astuce: concaténer la chaîne de deux morceaux. De cette façon, la balise de fermeture est coupée en deux et n'est plus une balise de fermeture valide. '?>' --> '?'.'>'

Dans votre code:

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

Cela fera // les commentaires fonctionnent.

Pour /* */ commentaires pour fonctionner, vous devez diviser le */ séquence aussi:

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

Rappelez-vous, parfois, même si l'ensemble est plus que la somme de ses parties - mais être gourmand est mauvais, il y a des moments où il vaut mieux se retrouver avec moins. :)

125
ppeterka

La manière la plus simple

Créez une variable distincte pour contenir votre expression régulière; de cette façon, vous pouvez simplement commenter l'instruction preg_replace():

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

Correction en utilisant des classes de caractères

Pour corriger les commentaires de ligne, vous pouvez diviser ?> en mettant > à l'intérieur d'une classe de caractères comme ceci:

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

Pour corriger les commentaires de bloc, vous pouvez l'appliquer à /:

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

Pour corriger les deux styles de commentaire, vous pouvez mettre / et> dans leur propre classe de personnage.

Correction en utilisant le /x modificateur

Le xmodificateur - aka PCRE_EXTENDED - ignore les espaces et les retours à la ligne dans une expression régulière (sauf lorsqu'ils se produisent à l'intérieur d'une classe de caractères); cela permet d'ajouter des espaces pour séparer les caractères problématiques. Pour corriger les deux styles de commentaire:

$string = preg_replace('#<br\s* /? >(?:\s*<br\s* /? >)+#ix', '<br />', $string);
                               ^  ^             ^  ^
74
Ja͢ck

Pourquoi vos tentatives n'ont pas fonctionné:

// $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

Ce qui fonctionne:

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

Plus loin ...

Après ce qui précède, vous devriez pouvoir utiliser /* pour commenter la ligne. Si vous quittez le ?> intact, // ne peut pas commenter une ligne entière. Le texte suivant ?> pourrait être du html, ce qui est hors du contrôle de l'interpréteur PHP, donc cela ne fonctionnerait pas.

De la documentation:

Les styles de commentaire "une ligne" ne commentent que la fin de la ligne ou le bloc courant de PHP, selon la première éventualité. Cela signifie que le code HTML après // ...?> ou # ...?> SERA imprimé:?> sort du PHP et retourne en mode HTML, // ou # ne peut pas influencer cela.

39

Une autre idée: échapper au > (et le /, si vous souhaitez utiliser un /*...*/ commentaire):

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

Un échappement "inutile" est ignoré par le moteur d'expression régulière, mais est utile dans ce cas (pour les raisons décrites dans les autres réponses).

16
Tim Pietzcker

Pourquoi utiliser des "astuces" compliquées et difficiles à lire pour contourner le problème?

? n'est qu'un raccourci quantificateur pour plus de commodité, donc

tilisez simplement la version longue du quantificateur {0,1}, signifie "minimum 0 maximum 1 occurrence":

$string = preg_replace('#<br\s*/{0,1}>(?:\s*<br\s*/{0,1}>)+#i', '<br />', $string);
11
stema

Quelques autres façons qui valent la peine d'être ajoutées au livre astuces RegEx:

Tout d'abord, vous pouvez compacter votre RegEx pour: /(<br\s*/?>)+/i et le remplacer par <br /> (Pas besoin de surcharger le RegExP avec des lookaheads) et vous vous retrouverez toujours avec le saut de ligne XHMTL que vous avez choisi.

Autres façons de modifier votre RegEx pour qu'il ne déclenche pas le commentaire de fin */ Ou le script de fin ?>:

  • Utilisez quantificateurs possessifs : #(<br\s*+/?+>)+#i - ce qui signifie essentiellement pour \s*+ Si vous avez trouvé des espaces correspondant autant qu'il y en a et conservez-les, et pour /?+ si vous avez trouvé une barre oblique, gardez-la!
  • Mettez \s* Et /* Dans les groupes de capture => #(<br(\s*)(/?)>)+#i

Démos en direct: http://codepad.viper-7.com/YjqUbi

Et puisque nous avons appuyé le comportement possessif, le RegEx le plus rapide qui contourne également le problème de commentaire est: #(<br\s*+/?+>)++#idémo expliquée


Quant aux commentaires dans des situations délicates

Lorsque vous ne pouvez pas modifier le code, ou avez déjà utilisé un commentaire multiligne et:

1. Utilisez un nowdoc:

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

Code en direct: http://codepad.viper-7.com/22uOtV

Remarque: un nowdoc est similaire à un heredoc mais il n'analyse pas le contenu et doit avoir son début délimiteur entouré de ' guillemets simples ' ( notez que le le délimiteur de fin ne peut pas être identifié , doit être suivi de ; et d'une nouvelle ligne !)

2. Sautez sur le code avec un goto :

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

Exemple en direct: http://codepad.viper-7.com/UfqrIQ

3. Sautez le code avec if(false) ou if(0):

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

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

9
CSᵠ