【问题标题】:Convert PHP closing tag into comment将 PHP 结束标记转换为注释
【发布时间】:2013-02-19 14:51:04
【问题描述】:

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

我尝试用///**/# 注释掉这一行,但它们都不起作用,解析器认为结束标记是一个实际的结束标记。

这是有问题的行:

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

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

【问题讨论】:

  • 有趣的问题,但真实存在。我投赞成票。
  • 天啊。起初我对你的问题持怀疑态度,准备问问题出在哪里,但后来我尝试用包含'?>'的字符串评论一行,我明白了。这应该添加到phpsadness.com 的长列表中
  • php.net/manual/en/language.basic-syntax.comments.php 解释了这种“功能”的用处,它在单行的情况下很有用&lt;?php # echo 'simple';?&gt;
  • @lolesque 感谢您的链接。一个很好的。一个相关的也涵盖其他语言:wiki.theory.org/YourLanguageSucks
  • @OndraŽižka 他所做的只是删除重复的 br 标签。一个正则表达式可以很好地解决这个问题。仅仅因为它有时很糟糕并不意味着它一直都很糟糕。

标签: php regex tags comments


【解决方案1】:

使用一个技巧:连接两个部分的字符串。这样,结束标签被一分为二,不再是有效的结束标签。 '?&gt;' --&gt; '?'.'&gt;'

在您的代码中:

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

这将使// cmets 工作。

要使/* */ cmets 工作,您还必须拆分*/ 序列:

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

请记住,有时,即使整体更多比其部分的总和 - 但贪婪是不好的,有时你最好留下 less。 :)

【讨论】:

  • @ppeterka 哇,我什至没有想到这一点。谢谢。
  • 两天前我不得不在 C 中使用这个技巧来处理包含??&lt;的字符串
  • 伟大的。为什么我从来不这么想!?
【解决方案2】:

最简单的方法

创建一个单独的变量来保存你的正则表达式;这样你就可以简单地注释掉preg_replace() 声明:

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

使用字符类修复

要修复行 cmets,您可以通过将 &gt; 放入字符类中来分解 ?&gt;,如下所示:

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

要修复block cmets,你可以将它应用到/

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

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

使用/x 修饰符修复

x modifier - 又名PCRE_EXTENDED - 忽略正则表达式中的空格和换行符(除非它们出现在字符类中);这使得添加空格来分隔有问题的字符成为可能。修复两种评论样式:

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

【讨论】:

  • @Cthulhu +1(当然也是为了答案)。此外(至少对我而言)这使得正则表达式更难理解。不是很多,但是如果我看到这个正则表达式,我会说:嗯,这是怎么回事?但这完全是主观的。
  • @ppeterka 我有点同意,所以我找到了另一种方法,使用 x 修饰符:)
  • @Jack Nice,我会再给它+1,我学到了一些新东西......我一直忘记正则表达式修饰符(除了g,我很少使用它们).. .
  • @Jack 谢谢你,我从解决方案中学到了关于正则表达式的新东西。
  • +1 用于将正则表达式分离到前一行。它使正则表达式保持不变,但仍允许注释掉逻辑。
【解决方案3】:

为什么你的尝试没有成功:

// $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',...
                                    ^ ^              ^ ^

进一步...

完成上述操作后,您应该可以使用/* 注释掉该行。 如果你保持?&gt; 不变,// 不可能注释掉整行。 ?&gt; 后面的文本可能是 html,它在 PHP 解释器的控制之外,所以这不起作用。

来自the documentation:

“单行”注释样式仅注释到行尾或 当前的 PHP 代码块,以先到者为准。这意味着 // ... ?> 或 # ... ?> 之后的 HTML 代码将被打印:?> 爆发 PHP 模式并返回 HTML 模式,并且 // 或 # 不能影响 那个。

【讨论】:

  • 谢谢,还有很多我不知道的东西……很有帮助。
  • 这篇文章应该得到更多的 +1... 仅用于彻底的解释。
【解决方案4】:

另一个想法:转义 &gt;(和 /,如果你想使用 /*...*/ 评论):

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

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

【讨论】:

  • @ppeterka:我使用反斜杠而不是字符类(但是是的,我确实错过了一次。谢谢!)
  • 对不起,我好像累了...我注意到第二个,它被留在了 []...
【解决方案5】:

为什么要使用复杂、难以阅读的“技巧”来解决问题?

? 只是方便起见的量词快捷方式,所以

只用长版的量词{0,1},意思是“最少0次最多1次出现”:

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

【讨论】:

  • +1 这个页面开始成为收集正则表达式技巧的好地方。
  • @ppeterka,我实际上将所有其他答案称为“技巧”,但我的答案只是使用量词的长版本而不是快捷方式。
  • 无意冒犯,只是在我的字典中,使用表达式的长版本而不是更短、更方便的句法糖也被视为一种技巧......
【解决方案6】:

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

首先,您可以将您的 RegEx 压缩为:/(&lt;br\s*/?&gt;)+/i 并替换为 &lt;br /&gt;(无需为 RegExP 带来前瞻负担),您将始终得到您选择的 XHMTL 换行符。

其他修改 RegEx 的方法,使其不会出错 */ end comment 或 ?&gt; end script:

  • 使用possessive quantifiers : #(&lt;br\s*+/?+&gt;)+#i - 如果您发现空格匹配尽可能多并保留它,则基本上意味着\s*+,如果您发现斜线,则使用/?+
  • \s*/* 包含在捕获组中=> #(&lt;br(\s*)(/?)&gt;)+#i

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

并且由于我们倾向于所有格行为,因此也绕过评论问题的最快正则表达式是:#(&lt;br\s*+/?+&gt;)++#i explained demo


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

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

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 类似于 heredoc,但它不解析内容,必须将其 开始 分隔符包含在 @ 987654341@single quotes'注意不能识别结束分隔符,后面必须跟;换行! em>)

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

【讨论】:

    猜你喜欢
    • 2015-01-25
    • 1970-01-01
    • 2018-10-23
    • 2012-04-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-28
    • 2010-12-03
    • 1970-01-01
    相关资源
    最近更新 更多