Convert PHP closing tag into comment

PhpRegexTagsComments

Php Problem Overview


One of the lines in my script contains a PHP closing tag inside a string. Under normal operation this does not cause a problem, but I need to comment out the line.

I have tried to comment out this line with //, /* */ and # but none of them work, the parser considers closing tag to be an actual closing tag.

Here is the line in question:

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

What can I do to comment out the above line?

Php Solutions


Solution 1 - Php

Use a trick: concatenate the string from two pieces. This way, the closing tag is cut in two, and is not a valid closing tag anymore. '?>' --> '?'.'>'

In your code:

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

This will make // comments work.

For /* */ comments to work, you'd have to split the */ sequence too:

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

Remember, sometimes, even though the whole is more than the sum of its parts - but being greedy is bad, there are times you are better left with less. :)

Solution 2 - Php

The easiest way

Create a separate variable to hold your regular expression; this way you can simply comment out the preg_replace() statement:

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

Fix using character classes

To fix line comments, you can break up ?> by putting > inside a character class like so:

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

To fix block comments, you can apply it to /:

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

To fix both comment styles, you can put / and > in their own character class.

Fix using the /x modifier

The x modifier - aka PCRE_EXTENDED - ignores spaces and newlines in a regular expression (except when they occur inside a character class); this makes it possible to add spaces to separate the problematic characters. To fix both comment styles:

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

Solution 3 - Php

Why your attempts didn't work:

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

What works:

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

Further...

After the above, you should be able to use /* to comment out the line. If you leave the ?> intact, // cannot possibly comment out an entire line. The text following ?> could be html, which is outside the control of the PHP interpreter, so that wouldn't work.

From the documentation:

> The "one-line" comment styles only comment to the end of the line or > the current block of PHP code, whichever comes first. This means that > HTML code after // ... ?> or # ... ?> WILL be printed: ?> breaks out > of PHP mode and returns to HTML mode, and // or # cannot influence > that.

Solution 4 - Php

Another idea: Escape the > (and the /, if you want to use a /*...*/ comment):

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

An "unnecessary" escape is ignored by the regex engine, but is useful in this case (for reasons outlined in the other answers).

Solution 5 - Php

Why use complicated, difficult to read "tricks" to work around the problem?

? is just a quantifier shortcut for convenience, so

Just use the long version of the quantifier {0,1}, means "minimum 0 maximum 1 occurrence":

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

Solution 6 - Php

A few other ways worth adding to the RegEx trick book:

First you could compact your RegEx to: /(<br\s*/?>)+/i and replace with <br /> (no need to burden the RegExP with lookaheads) and you'll always end up with your chosen XHMTL line break.

Other ways to modify your RegEx so it won't trip */ end comment or ?> end script:

  • Use possessive quantifiers : #(<br\s*+/?+>)+#i - which basically mean for \s*+ if you found whitespace match as many as there are and keep it, and for /?+ if you found a slash keep it!
  • Enclose \s* and /* in capture groups => #(<br(\s*)(/?)>)+#i

Live demos: http://codepad.viper-7.com/YjqUbi

And since we leaned the possessive behavior the fastest RegEx that also bypasses the commenting problem is: #(<br\s*+/?+>)++#i explained demo


As for commenting in tricky situations

When you can't change the code, or have already used a multiline comment and:

  1. Use a nowdoc:

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

Live code: http://codepad.viper-7.com/22uOtV

Note: a nowdoc is similar to a heredoc but it does not parse the content and has to have it's starting delimiter enclosed in 'single quotes' (note that the ending delimiter can't be idented, must be followed by ; and a new line !)

  1. Jump over the code with a goto:

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

Live example: http://codepad.viper-7.com/UfqrIQ

  1. Jump over the code with if(false) or 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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionv1n_vampireView Question on Stackoverflow
Solution 1 - PhpppeterkaView Answer on Stackoverflow
Solution 2 - PhpJa͢ckView Answer on Stackoverflow
Solution 3 - PhpAnirudh RamanathanView Answer on Stackoverflow
Solution 4 - PhpTim PietzckerView Answer on Stackoverflow
Solution 5 - PhpstemaView Answer on Stackoverflow
Solution 6 - PhpCSᵠView Answer on Stackoverflow