【问题标题】:PHP RegEx not matching a string that it should matchPHP RegEx 不匹配它应该匹配的字符串
【发布时间】:2019-12-07 03:11:21
【问题描述】:

这让我发疯了......

我有以下代码:

    # open pdf
    $pdf = file_get_contents('myfile.pdf');

    echo("RE 1:\n");
    preg_match('/^[0-9]+ 0 obj.*\/Contents \[ ([0-9]+ [0-9]+) R \\]/msU', $pdf, $m);
    var_dump($m);

    echo("\nRE 2:\n");
    preg_match('/^8 0 obj.*\/Contents \[ ([0-9]+ [0-9]+) R \\]/msU', $pdf, $m);
    var_dump($m);

文件 myfile.pdf 包含以下文本:

...
8 0 obj
<<
/Type /Page
/Parent 2 0 R
/Resources 6 0 R
/Contents [ 5 0 R ]
>>
endobj
...

这两个正则表达式之间的唯一区别是字符串开头的数字范围。然而我得到以下输出:

RE 1:
array(0) {
}

RE 2:
array(2) {
  [0]=>
  string(78) "8 0 obj
<<
/Type /Page
/Parent 2 0 R
/Resources 6 0 R
/Contents [ 5 0 R ]"
  [1]=>
  string(3) "5 0"
}

我希望两个正则表达式都返回相似的结果,但是以数字范围开头的正则表达式 (RE 1) 不会返回任何结果。这是一个错误还是我做错了什么?

更新

添加preg_last_error() 后,我得到PREG_BACKTRACK_LIMIT_ERROR。我该如何解决?

【问题讨论】:

  • @Emma 是的,这就是我想要捕捉的。它在 regex101.com 上完美运行,但在我的代码中却不行。
  • 您的两个正则表达式在sandbox.onlinephpfunctions.com 都可以正常工作,所以可能是您的 PHP 或 PCRE 版本引起了头痛?
  • 尝试使用preg_last_error() 看看它是否能给你任何提示。
  • @MonkeyZeus 好电话!我收到 PREG_BACKTRACK_LIMIT_ERROR。
  • 检查您的php.ini 文件并查看pcre.backtrack_limit 的设置,如果您无权访问php.ini,请使用echo ini_get( 'pcre.backtrack_limit' );

标签: php regex


【解决方案1】:

我猜你可能正在设计一个看起来有点像的表达式,

[0-9]+\s+0\s+obj\b.*?\/Contents\s+\[\s*([0-9]+\s+[0-9]+)\s+R\s*\]

开启s 模式。

测试

$re = '/[0-9]+\s+0\s+obj\b.*?\/Contents\s+\[\s*([0-9]+\s+[0-9]+)\s+R\s*\]/s';
$str = '8 0 obj
<<
/Type /Page
/Parent 2 0 R
/Resources 6 0 R
/Contents [ 5 0 R ]
>>
endobj

8 0 obj
<<
/Type /Page
/Parent 2 0 R
/Resources 6 0 R
/Contents [ 5 0 R ]
>>
endobj';

preg_match_all($re, $str, $matches, PREG_SET_ORDER, 0);

var_dump($matches);

表达式在regex101.com 的右上方面板中进行了解释,如果您想探索/简化/修改它,在this link 中,您可以查看它如何与一些示例输入进行匹配,如果您愿意的话。

正则表达式电路

jex.im 可视化正则表达式:

【讨论】:

  • OP 使用的是/msU,所以他们的. 匹配所有内容,包括换行符。
  • 是的,但是 RE 确实有效。我的 preg_last_error() 输出是 PREG_BACKTRACK_LIMIT_ERROR。所以这就是为什么我的不起作用我猜。但我不确定是什么原因造成的......
  • 你的作品与 /msU 一起使用。我想知道这是否是您使用的词边界...现在测试更多的东西。
  • 好的,你的工作因为你添加了 .*?量词。我已经在使用 /U 修饰符,这意味着 Ungreedy。但是你的 .*?扭转了这一点。但我需要它不贪婪,因为我试图捕获这个字符串的很多实例。
  • 我明白了。它将在 regex101.com 中失败。但两者在 PHP 中都是可以接受的。我都试过了,它们产生了完全相同的结果。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-22
  • 2021-08-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-19
相关资源
最近更新 更多