PHP:提取数字并用函数替换字符串中所有出现的地方

PHP: Extract digits and replacing all occurrences from a string with functions

我有这个字符串:

$string = '[userid=77] has created a new task.
[userid=59] and [userid=66] is are subscribed.
This task is assigned to [accountid=2248]';

我想displayuser(DIGIT)替换所有 [userid=DIGIT],用displayaccount(DIGIT)替换所有[accountid=DIGIT]

所以字符串应该这样结束:

$string = displayuser(77).' has created a new task.
    '.displayuser(59).' and '.displayuser(66).' is are subscribed.
    This task is assigned to '.displayaccount(2248).';

到目前为止我试过的只显示 第一个 [userid=DIGIT].

$text = "[userid=77] has created a new task. [userid=59] and [userid=66] is are subscribed. This task is assigned to [accountid=28]";
print "Before: ".$text."<br/><br/>";

$matches = array();

// Get [userid=DIGIT]
$found = preg_match('@\[userid[^\]]+\]@', $text, $matches);
print $matches[0]."<br/><br/>";

// Get DIGIT withing [userid=DIGIT]
$found2 = preg_match('!\d+!', $matches[0], $match_id);
echo $match_id[0]."<br/><br/>";

// Replace [userid=DIGIT] with function(DIGIT)
$new = str_replace($matches[0],displayuser($match_id[0]),$text);

您可以使用正则表达式匹配并捕获 useridaccountid 之后的数字,以及 preg_replace_callback function 将捕获的值映射到匿名回调中的必要字符串作为第二个参数传递的函数:

$text = preg_replace_callback('@\[userid=(\d+)]|\[accountid=(\d+)]@', function($m) {
    return !empty($m[1]) ? displayuser($m[1]) : displayaccount($m[2]);
}, $text);

参见PHP demo

\[userid=(\d+)]|\[accountid=(\d+)] 模式将匹配 [userid=<DIGITS_HERE>] 将数字放入第 1 组或 [accountid=<DIGITS_HERE>] 将这些数字放入第 2 组。在回调中使用 !empty($m[1]),我们检查如果第 1 组匹配,如果匹配,则使用 displayuser($m[1]) 通过用户 ID 获取用户名,否则我们使用 displayaccount($m[2]) 通过帐户 ID 获取帐户名。

按照@h2oooooooo 的建议使用 preg_replace_callback 我想出了以下完美的方法

$text = "[userid=77] has created a new task. [userid=59] and [userid=66] is are subscribed. This task is assigned to [accountid=4]";

function displaycontact_cb($matches){
  $found2 = preg_match('!\d+!', $matches[0], $match_id);
  return displayuser($match_id[0]);
}

function displayaccount_cb($matches){
  $found2 = preg_match('!\d+!', $matches[0], $match_id);
  return displaycontact($match_id[0],"account");
}

$text = preg_replace_callback('@\[userid[^\]]+\]@',"displaycontact_cb",$text);
$text = preg_replace_callback('@\[accountid[^\]]+\]@',"displayaccount_cb",$text);

print $text;