5

基本上,我需要一个正则表达式来匹配 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...";

"它应该匹配并替换应该用 a替换的所有位置',这意味着理想情况下应该不理会 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 源代码。

4

2 回答 2

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. ETC...

概括

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

也可以看看

这个答案。这很值得。

于 2015-02-09T17:40:34.020 回答
5

这是一个利用标记器扩展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;

作为第一个参数传递的正则表达式是这里的关键。它告诉函数仅在字符串不包含$ (embedded variable "$a"){ (embedded variable type 2 "{$a[0]}")、换行符<>(HTML tag end/open symbols) 时才将字符串转换为其单引号等效项。它还检查字符串是否包含单引号,并防止替换以避免需要转义的情况。

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

于 2013-07-11T09:30:02.880 回答