php - 为什么 PHP 中 preg_match 的行为与 preg_replace 不同(导致不同的匹配)?

标签 php regex

鉴于以下字符串和正则表达式,所产生的行为是我不理解的。 preg_match 提供了我所期望的内容,而 preg_replace 对我来说没有意义。

$string = 'aaa [Ticket#RS-123456] äüö [xxx] ccc ddd';
$re = '@(.*)?(\[Ticket\#)(.*)(\])(.*)?@siU'; 

在这个例子中我最终需要的是字符串RS-123456(或者任何位于该位置的字符串)。如果我没有完全误解正则表达式,这个字符串应该在第三个位置($3)匹配。

preg_match($re, $string, $matches_pm);

Result (as expected):
Array(
    [0] => aaa [Ticket#RS-123456]
    [1] => aaa 
    [2] => [Ticket#
    [3] => RS-123456 // That's exactly what I would expect
    [4] => ]
)


$res_pr = preg_replace($re, "$3", $string);

Result (unexpected):
RS-123456 äüö [xxx] ccc ddd

我希望任何人都能睁开我的眼睛,告诉我我的逻辑失败隐藏在哪里。

最佳答案

两者都匹配相同的文本,但 preg_match 仅返回第一个匹配项,而 preg_replace 替换匹配项(这不是整个字符串)第 3 组内容在结果字符串中留下 äüö [xxx] ccc ddd

使用

$re = '@(.*)(\[Ticket\#)(.*?)(\])(.*)@si';  

使用 preg_matchpreg_replace 获得相同的结果。

请参阅PHP demo .

但是,preg_match 是此处的首选方式:

if (preg_match('@\[Ticket#\K[^]]+@i', $string, $matches_pm)) {
    echo $matches_pm[0];
}

参见this PHP demo .

图案详细信息

  • \[Ticket# - 文字 [Ticket# 子字符串
  • \K - 匹配重置运算符丢弃当前匹配的文本
  • [^]]+ - 除 ] 之外的 1 个或多个字符

关于php - 为什么 PHP 中 preg_match 的行为与 preg_replace 不同(导致不同的匹配)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49428257/

相关文章:

regex - 如何将模式与连字符或撇号匹配

c++ - 如何将 pcre_study 与 pcrecpp 一起使用?

phpmyadmin 带有外来字符的 csv 导入无法正常工作

java - 在 PHP 中使用 Java keystore

php - 如果我在 symfony2 中创建自定义事件,我如何访问实体管理器

session 数组中的php Post数组

R: gsub 标点字符只出现在字符串的末尾

javascript - Nodejs readFileSync 两个字符串之间的正则表达式标记

php - X-Frame-Options 拒绝加载

mysql - 如何在 rsyslog 中仅插入来自常规日志的 mac 地址?