【问题标题】:How can I make preg_replace work in all PHP environments?如何使 preg_replace 在所有 PHP 环境中工作?
【发布时间】:2018-11-09 22:43:37
【问题描述】:

我使用 preg_replace 的函数在开发服务器上运行良好,但在生产服务器上根本不行。该问题可能与编码有关。有没有办法让这个表达式不管编码如何都能工作?

$config 看起来像这样:

class JConfig {
    public $mighty = array("0" => array("0" => "/`?\\#__mightysites[` \\n]+/u"), "1" => array("0" => "`hhd_mightysites` "));
    public $mighty_enable = '0';
    public $mighty_language = '';
    public $mighty_template = '9';
    public $mighty_home = '';
    public $mighty_langoverride = '0';......

我将与我想剥离的行相关的变量放在一个名为 strips like 的数组中

$strips = array(
    'mighty',
    'mighty_enable',
    'mighty_sync',
    'mighty_language',
    'mighty_template',.....

然后使用循环将这些行去掉:

foreach ($strips as $var) {
    if (JString::strpos($config, 'public $' . $var . ' =') !== false) {
        $config = preg_replace('/\tpublic \$' . $var . ' \= ([^\;]*)\;\n/u', '', $config);
        $tempvar .= $var . ", ";
    }
}

再次,它在我们的开发服务器上完美运行。它不会对生产服务器上的任何行做任何事情。我也知道它通过 strpos 喜欢到达 preg_replace 行。我可以做 preg_replace 环境证明吗?

感谢您的帮助,因为它只发生在生产服务器上,很难测试!

【问题讨论】:

  • 什么不起作用?它会导致错误吗?
  • 源文件一样吗?或者服务器上的那个有\r而不是\n
  • 您不需要转义正则表达式中的所有内容。等号和分号并不特殊,而且你也有一个不需要的组。这应该足够了:'/\tpublic \$' . $var . ' = [^;]+;\n/u' 或者,因为你不关心内容,'/^\s*public \$' . $var . ' =.*$/' 应该没问题。
  • 不,只返回与 preg_replace 之前完全相同的行/文件。我怀疑它不匹配。我将两个不同服务器的两个文件从我的电脑新复制到 winmerge 中,它是 100% 红色的。所以我相信服务器对它们进行不同编码的方式?也许这就是它不匹配的原因?
  • 开发服务器上的更改有效,您认为这会解决生产服务器上的问题吗?

标签: php encoding preg-replace


【解决方案1】:

最安全的选择是不要“信任”您希望匹配的任何文字空格/制表符。

我会推荐 \s+\s,而不是 \t

此外,为了涵盖操作系统可能在每行末尾使用\r\n\n 的情况,您可以使用\R 来匹配这两种变体。

我将通过^ 在模式的开头包含行首字符检查,m 作为模式修饰符。这可确保我们匹配并且仅匹配您期望在行首出现 \t 的位置。

最后,preg_replace() 有一个可选的第 5 个参数,用于计算进行了多少次替换。如果$found 是非零值,则存储当前的$var 值。

代码:(Demo)

$config = <<<'CONFIG'
class JConfig {
    public $mighty = array("0" => array("0" => "/`?\\#__mightysites[` \\n]+/u"), "1" => array("0" => "`hhd_mightysites` "));
    public $mighty_enable = '0';
    public $mighty_language = '';
    public $mighty_template = '9';
    public $mighty_home = '';
    public $mighty_langoverride = '0';......
CONFIG;

$strips = [
    'mighty',
    'mighty_enable',
    'mighty_sync',
    'mighty_language',
    'mighty_template'
];

$tempvar = '';
foreach ($strips as $var) {
    $config = preg_replace('~^\s+public\s\$' . $var . '\s=\s[^;]*;\R~um', '', $config, -1, $found);
    if ($found) {
        $tempvar .= $var . ", ";
    }
}
echo "\$tempvar = $tempvar\n\n";
echo $config;

输出:

$tempvar = mighty, mighty_enable, mighty_language, mighty_template, 

class JConfig {
    public $mighty_home = '';
    public $mighty_langoverride = '0';......

附言最后一项建议改进...如果您的项目实际上不需要$tempvar 变量(意味着您仅在调试期间使用它),那么您可以完全避免循环,只需@ 987654338@,将生成的字符串包装在()中,另存为$var,然后调用preg_replace()一次。这会更有效率,并且您的样本$strips 数据不需要使用preg_quote() 准备,因为您需要转义“特殊字符”。

【讨论】:

  • 谢谢!我会在 12 小时内测试出来。
  • 完美运行。感谢您实施 $found - 非常有帮助!
猜你喜欢
  • 2016-05-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-08
  • 1970-01-01
  • 1970-01-01
  • 2014-11-16
  • 2021-12-20
相关资源
最近更新 更多