Reputation: 1595
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?
Upvotes: 153
Views: 7369
Reputation: 173662
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);
^ ^ ^ ^
Upvotes: 73
Reputation: 10169
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:
#(<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!\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
When you can't change the code, or have already used a multiline comment and:
$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 !)
$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
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
Upvotes: 8
Reputation: 336498
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).
Upvotes: 15
Reputation: 93086
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);
Upvotes: 10
Reputation: 20736
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. :)
Upvotes: 124
Reputation: 46788
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.
Upvotes: 38