将PHP结束标记转换为注释


149

我的脚本中的其中一行包含一个字符串内的PHP结束标记。在正常操作下,这不会引起问题,但是我需要注释掉该行。

我试图注释掉这一行///* */#但没有工作,解析器认为结束标记是一个实际的结束标记。

这是有问题的行:

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

我该怎么做才能注释掉上面的行?


18
有趣的问题,但是真实的。我投票。
Voitcus

17
我的天啊。起初,我对您的问题表示怀疑,准备问问题出在哪里,但是后来我尝试用包含'?>'的字符串注释一行,然后我就明白了。这应该添加到phpsadness.com
lolesque 2013年

6
php.net/manual/en/language.basic-syntax.comments.php中解释了这种“功能”的有用性,在单线情况下很有用<?php # echo 'simple';?>
lolesque 2013年

2
@lolesque感谢您的链接。好人 相关的语言也涵盖了其他语言:wiki.theory.org/YourLanguageSucks
Simon Forsberg,

5
@OndraŽižka他所做的只是删除重复的br标签。正则表达式可以正常工作。仅仅因为它有时很糟糕并不意味着它一直都不好。
Kip 2013年

Answers:


124

使用技巧:将字符串分为两部分。这样,结束标记被切成两半,不再是有效的结束标记。'?>' --> '?'.'>'

在您的代码中:

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

这将使//评论起作用。

为了使/* */注释生效,您还必须拆分*/序列:

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

记住,有时候,即使整个就是更加大于部分的总和-但贪婪是不好的,有你更好地留时间较少。:)


@ppeterka哇,我什至都没有想到。谢谢。
v1n_vampire

1
2天前,我不得不在C中使用此技巧来生成包含??<
Ryan Amos

2
太好了 为什么我从来没有那样想!!
2013年

73

最简单的方法

创建一个单独的变量来保存您的正则表达式;这样,您可以简单地注释掉该preg_replace()语句:

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

使用字符类修复

要修复行注释,您可以?>通过放入如下>字符类来分解:

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

要修复块注释,可以将其应用于/

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

要修复这两种注释样式,您可以将/ >放在自己的字符类中。

使用/x修饰符修复

x 改性剂 -又名PCRE_EXTENDED-忽略空格和换行符在正则表达式(当它们出现在字符类内除外); 这样就可以添加空格来分隔有问题的字符。要修复两种注释样式:

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

@Cthulhu +1(当然,答案也是)。同样(至少对我而言),这使正则表达式更难理解。不是很多,但是如果我看到这个正则表达式,我会说:嗯,这是怎么回事?但这是彻头彻尾的,完全是主观的。
ppeterka

1
@ppeterka我部分同意,所以我找到了另一种方式,通过x修改:)
杰克

@杰克·尼斯(Jack Nice),我为此再加+1,我学到了一些新东西...我一直忘了正则表达式修饰符(除了,我很少使用它们g)...
ppeterka 2013年

@Jack谢谢,我从解决方案中学到了有关正则表达式的新知识。
v1n_vampire

1
+1用于将正则表达式分离到较早的行。它使正则表达式保持不变,但仍允许逻辑被注释掉。

38

为什么您的尝试不起作用:

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

什么有效:

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

进一步...

完成上述操作后,您应该可以使用/*注释掉该行。如果您?>保持原样,//则不能注释掉整行。下面的文本?>可能是html,不在控件范围内了PHP解释器范围,因此无法正常工作。

文档中:

“单行”注释样式仅注释到该行的末尾或当前PHP代码块,以先到者为准。这意味着将打印// // ...?>或#...?>之后的HTML代码:?>脱离PHP模式并返回HTML模式,并且//或#无法影响它。


谢谢,还有很多我还是不知道的事情。
v1n_vampire

4
这篇文章应获得更多的+1 ...仅作详尽的解释。
ppeterka

15

另一个想法:跳出>(和/,如果要使用/*...*/注释,则转义):

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

正则表达式引擎会忽略“不必要的”转义,但在这种情况下很有用(由于其他答案中概述的原因)。


@ppeterka:我使用了反斜杠代替了字符类(但是,是的,我确实错过了一次。谢谢!)
Tim Pietzcker 2013年

抱歉,似乎我很累...我注意到了第二个,它留在了[]的周围...
ppeterka 2013年

10

为什么使用复杂的,难以理解的“技巧”来解决问题?

? 只是为了方便而使用的量词捷径,所以

只需使用量词的长版本{0,1},即“最少0个最多1个出现”:

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

1
+1这个页面开始是收集正则表达式技巧的一个好地方,让我们牢记在心。
ppeterka

1
@ppeterka,我实际上将所有其他答案都称为“技巧”,但我的答案只是使用量词的长版本而不是快捷方式。
13年

3
没有冒犯,只是在我的字典中,使用长版本的表达式而不是更短,更方便的语法糖,这也算是一种技巧...
ppeterka,2013年

8

值得添加到RegEx技巧手册中的其他几种方法

首先,您可以将RegEx压缩为:/(<br\s*/?>)+/i并替换为<br />(无需使RegExP负担过多),您将始终以选择的XHMTL换行符结束。

修改RegEx的其他方法,使它不会跳到*/结束注释或?>结束脚本:

  • 使用所有格修饰符#(<br\s*+/?+>)+#i-基本上意味着,\s*+如果发现空白匹配并保持空白,并且/?+如果发现斜杠,则保留!
  • 将其围起来\s*/*放在捕获组中=>#(<br(\s*)(/?)>)+#i

现场演示: http //codepad.viper-7.com/YjqUbi

由于我们倾斜了所有格行为,因此绕过评论问题的最快RegEx是:解释性演示#(<br\s*+/?+>)++#i


至于在棘手的情况下发表评论

当您无法更改代码或已经使用多行注释并且:

1.使用nowdoc

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

实时代码:http//codepad.viper-7.com/22uOtV

注:一个nowdoc类似于定界符,但它不解析的内容,必须有它的起始定界符括在'单引号'请注意,结束符不能idented,必须跟;新行

2.使用goto跳过代码:

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

实时示例:http//codepad.viper-7.com/UfqrIQ

3.用if(false)或跳过代码if(0)

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

测试:http//codepad.viper-7.com/wDg5H5

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.