【问题标题】:Why does this preg_replace call return NULL?为什么这个 preg_replace 调用返回 NULL?
【发布时间】:2019-03-31 15:38:11
【问题描述】:

为什么这个调用返回 NULL? 正则表达式错了吗?使用 test 输入时,它不会返回 NULL。 文档说 NULL 表示错误,但它可能是什么错误?

$s = hex2bin('5b5d202073205b0d0a0d0a0d0a0d0a20202020202020203a');
// $s = 'test';
$s = preg_replace('/\[\](\s|.)*\]/s', '', $s);
var_dump($s);

// PHP 7.2.10-1+0~20181001133118.7+stretch~1.gbpb6e829 (cli) (built: Oct  1 2018 13:31:18) ( NTS )

【问题讨论】:

  • 你需要在这里做什么?您的 $s 没有第二个 ] 因此没有匹配项。还有,(\s|.)*不是必须的,不好用,就用.*(preg_replace("/\[].*]/s", "", $s))
  • 在正则表达式周围使用单引号而不是双引号也是一个好主意。否则,您将面临将正则表达式转义序列作为字符串转义序列处理的风险。
  • @WiktorStribiżew 我主要想知道为什么这会返回 NULL。如果不匹配,则应该返回输入,不是吗?
  • 如果正则表达式无效,则返回NULL
  • (\s|.) 有什么意义。 . 已经匹配 \s..

标签: php regex pcre


【解决方案1】:

您的正则表达式导致 catastrophic backtracking 并导致 PHP 正则表达式引擎失败。您可以使用preg_last_error() function 进行检查。

$r = preg_replace("/\[\](\s|.)*\]/s", "", $s);
if (preg_last_error() == PREG_BACKTRACK_LIMIT_ERROR) {
    print 'Backtrack limit was exhausted!';
}

输出:

Backtrack limit was exhausted!

由于此错误,您将从 preg_replace 获得 NULL 返回值。根据PHP doc of preg_replace

如果找到匹配项,则返回新的主题,否则主题将保持不变或如果发生错误则返回NULL


修复:在使用 s 修饰符 (DOTALL) 时不需要 (\s|.)。因为在使用 s 修饰符时,点匹配任何字符,包括换行符。

你应该只使用这个正则表达式:

$r = preg_replace('/\[\].*?\]/s', "", $s);
echo preg_last_error();
//=> 0

【讨论】:

    猜你喜欢
    • 2015-10-21
    • 2018-12-10
    • 1970-01-01
    • 2012-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-09
    • 1970-01-01
    相关资源
    最近更新 更多