正则表达式匹配php标签内没有变量的双引号字符串

时间:2013-07-11 08:56:30

标签: php regex html-parsing

基本上我需要一个正则表达式来匹配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源代码。

2 个答案:

答案 0 :(得分:6)

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. 内部<?php<?=代码
  2. 不在评论中
  3. 在报价单中
  4. 什么类型的报价?
  5. 是否是该类型的引用?
  6. 前面是\(转义)吗?
  7. \是否已转义?
  8. 等...
  9. 摘要

    你可以为此写一个正则表达式。 你可以用一些反向引用和大量的时间和关心来管理。 它会很难,你可能会浪费很多时间,如果你需要修复它,你就不会理解你写的正则表达式。

    另见

    This answer。这是值得的。

答案 1 :(得分:5)

这是一个利用tokenizer扩展仅将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 "{$a[0]}",新行,<>(HTML标记结束/打开符号)。它还检查字符串是否包含单引号,并防止替换以避免需要转义的情况。

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