【问题标题】:Regex to match double quoted strings without variables inside php tags正则表达式匹配双引号字符串,没有 php 标签内的变量
【发布时间】:2013-07-11 08:56:30
【问题描述】:

基本上,我需要一个正则表达式来匹配 PHP 标记内的所有双引号字符串,而其中没有变量。

这是我目前所拥有的:

"([^\$\n\r]*?)"(?![\w ]*')

并替换为:

'$1'

不过,这也会匹配 PHP 标记之外的内容,例如 HTML 属性。

示例案例:

<a href="somelink" attribute="value">Here's my "dog's website"</a>
<?php
    $somevar = "someval";
    $somevar2 = "someval's got a quote inside";
?>
<?php
    $somevar3 = "someval with a $var inside";
    $somevar4 = "someval " . $var . 'with concatenated' . $variables . "inside";
    $somevar5 = "this php tag doesn't close, as it's the end of the file...";

它应该匹配并替换所有应该将" 替换为' 的位置,这意味着最好不要单独使用html 属性。

替换后的示例输出:

<a href="somelink" attribute="value">Here's my "dog's website"</a>
<?php
    $somevar = 'someval';
    $somevar2 = 'someval\'s got a quote inside';
?>
<?php
    $somevar3 = "someval with a $var inside";
    $somevar4 = 'someval ' . $var . 'with concatenated' . $variables . 'inside';
    $somevar5 = 'this php tag doesn\'t close, as it\'s the end of the file...';

能够匹配内部脚本标签也很棒......但这可能会推动它进行一次正则表达式替换。

我需要正则表达式方法,而不是 PHP 方法。假设我在文本编辑器或 JavaScript 中使用 regex-replace 来清理 PHP 源代码。

【问题讨论】:

  • 使用preg_replace_callback()匹配php标签,并在回调中使用你的正则表达式。
  • @HamZa 如果 php 中有这样的东西怎么办:$a = '&lt;?php echo 'booooo!; ?&gt;';
  • @hek2mgl 你能告诉我在一般情况下发生这种情况的可能性吗?
  • @HamZa 检查我的答案。 tokenizer 做得很好。我认为该功能是解决问题的合理努力,因为简单的正则表达式解决方案的任何问题都会导致源文件损坏。
  • @DJDavid98 指出答案“不正确”本身就是不正确的。它以正确和安全的方式完成工作。也看看编辑历史,难怪这个帖子有点乱了。

标签: php regex html-parsing


【解决方案1】:

tl;博士

这真的太复杂了,无法用正则表达式完成。特别是不是一个简单的正则表达式。使用嵌套的正则表达式可能会更好,但您确实需要 lex/parse 才能找到您的字符串,然后您可以使用正则表达式对它们进行操作。

说明

您可以可能设法做到这一点。 您可能甚至可以做到这一点,甚至完美。 但这并不容易。 这将非常非常困难。

考虑一下:

Welcome to my php file. We're not "in" yet.

<?php
  /* Ok. now we're "in" php. */

  echo "this is \"stringa\"";
  $string = 'this is \"stringb\"';
  echo "$string";
  echo "\$string";

  echo "this is still ?> php.";

  /* This is also still ?> php. */

?> We're back <?="out"?> of php. <?php

  // Here we are again, "in" php.

  echo <<<STRING
    How do "you" want to \""deal"\" with this STRING;
STRING;

  echo <<<'STRING'
    Apparently this is \\"Nowdoc\\". I've never used it.
STRING;

  echo "And what about \\" . "this? Was that a tricky '\"' to catch?";

  // etc...

在双引号字符串中忘记匹配的变量名。 你能匹配这个例子中的所有字符串吗? 这对我来说就像一场噩梦。 SO 的语法高亮肯定不知道怎么处理。

您是否考虑过变量也可能出现在heredoc 字符串中?

我不想用正则表达式来检查:

  1. &lt;?php&lt;?= 代码内
  2. 不在评论中
  3. 在引用的报价中
  4. 引用的报价类型是什么?
  5. 是那种类型的引用吗?
  6. 前面是否有\(转义)?
  7. \ 转义了吗??
  8. 等等……

总结

您可能可以为此编写一个正则表达式。 您可能可以通过一些反向引用和大量时间和精力来管理。 这会很困难,而且您可能会浪费很多时间,而且如果您需要修复它,您将无法理解您编写的正则表达式。

另见

This answer。这是值得的。

【讨论】:

    【解决方案2】:

    这是一个利用标记器扩展将preg_replace 仅应用于 PHP 字符串的函数:

    function preg_replace_php_string($pattern, $replacement, $source) {
        $replaced = '';
        foreach (token_get_all($source) as $token) {
            if (is_string($token)){
                $replaced .= $token;
                continue;
            }
            list($id, $text) = $token;
            if ($id === T_CONSTANT_ENCAPSED_STRING) {
                $replaced .= preg_replace($pattern, $replacement, $text);
            } else {
                $replaced .= $text;
            }
        }
        return $replaced;
    }
    

    为了达到你想要的,你可以这样称呼它:

    <?php
        $filepath = "script.php";
        $file = file_get_contents($filepath);
        $replaced = preg_replace_php_string('/^"([^$\{\n<>\']+?)"$/', '\'$1\'', $file);
        echo $replaced;
    

    作为第一个参数传递的正则表达式是这里的关键。它告诉函数仅在字符串不包含 $ (嵌入变量 "$a"{ (嵌入变量类型 2 @987654327 @),新行,&lt;&gt;(HTML 标记结束/打开符号)。它还检查字符串是否包含单引号,并防止替换以避免需要转义的情况。

    虽然这是一种 PHP 解决方案,但它是最准确的解决方案。您可以使用任何其他语言获得最接近的结果,这需要您在某种程度上使用该语言构建自己的 PHP 解析器,以使您的解决方案准确。

    【讨论】:

    • 这是一种有趣的方法,但恐怕我无法使用 PHP 来满足我的需要!
    • 你要使用什么语言?
    猜你喜欢
    • 1970-01-01
    • 2016-04-18
    • 1970-01-01
    • 2016-08-20
    • 2016-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-15
    相关资源
    最近更新 更多