用前缀和后缀替换部分字符串

Replacing part of string with prefix and suffix

$str = ' I love [123] and [124] at (456). I hate [234] and [235] at (123).'

我想去

$str = 'I love <a title="a">[123]</a> and <a title="b">[124]</a> at <a title="XX">(456)</a>. I hate <a title="c">[234]</a> and <a title="d">[235]</a> at <a title="ZZ">(123)</a>.'

要用大括号 () 或 [] 替换的文本可以从 Table 1 或 Table 2 中找到。

Table 1
123 | a
124 | b
234 | c
235 | d

Table 2
456 | XX
123 | ZZ

当前方法

$text=explode(' ', $text);
for ($i=0; $i<count($text); $i++) {
    for ($j=0; $j<count($table1Col1); $j++) {
        if ($text[$i] == $table1Col1[$j])
            $text[$i] = '<a href="#" title="'.$table1Col2[$j].'">'.$table1Col1[$j].'</a>';
    }
    for ($j=0; $j<count($table2Col1); $j++) {
        if ($text[$i] == $table2Col1[$j])
            $text[$i] = '<a href="#" title="'.$table2Col2[$j].'">'.$table2Col1[$j].'</a>';
    }
}

如何改进代码以跳过不需要的循环?

我会考虑使用一个循环的方法,但由于数组具有相同的键,因此无法合并:

foreach($table1Col1 as $find => $repl) {
    $text = str_replace("[$find]",
                        "<a title=\"$repl\">[$find]</a>",
                        $text);
}

foreach($table1Col2 as $find => $repl) {
    $text = str_replace("($find)",
                        "<a title=\"$repl\">($find)</a>",
                        $text);
}

也许 preg_replace_callback 这里会更好?

$str = 'I love [123] and [124] at (456). I hate [234] and [235] at (123).';
$t1 = ['123'=>'a', '124'=>'b', '234'=>'c', '235'=>'d'];
$t2 = ['456'=>'XX', '123'=>'ZZ'];


$f1 = implode('|', array_map(fn ($k) => preg_quote($k), array_keys($t1)));
$f2 = implode('|', array_map(fn ($k) => preg_quote($k), array_keys($t2)));

$res = preg_replace_callback("/\[($f1)\]|\(($f2)\)/", function($m) use($t1, $t2) {
  // if first group has matched, then found key will be in `$m[1]`
  // if second group has matched, then found key will be in `$m[2]`
  $m1 = $m[1] ?? null;
  $m2 = $m[2] ?? null;
  if ($m1) {
    // use first table
    return '<a title="'.$t1[$m1].'">['.$m1.']</a>';
  }
  // use second table
  return '<a title="'.$t2[$m2].'">('.$m2.')</a>';
}, $str);

结果:

I love <a title="a">[123]</a> and <a title="b">[124]</a> at <a title="XX">(456)</a>. I hate <a title="c">[234]</a> and <a title="d">[235]</a> at <a title="ZZ">(123)</a>.

假设字符串中的所有值都出现在 table 中,您可以使用交替 | 来捕获 2 组中的每个数字,并使用该组索引到数组使用 preg_replace_callback.

的值
\[(\d+)]|\((\d+)\)

Regex demo | Php demo

$str = ' I love [123] and [124] at (456). I hate [234] and [235] at (123).';
$table1Col1=["123" => "a", "124" => "b", "234" => "c", "235" => "d"];
$table1Col2 = ["456" => "XX", "123" => "ZZ"];
$pattern = "/\[(\d+)]|\((\d+)\)/";

$result = preg_replace_callback($pattern, function($match) use ($table1Col1, $table1Col2) {
    return sprintf('<a title="%s">%s</a>',
        array_key_exists(2, $match) ? $table1Col2[$match[2]] : $table1Col1[$match[1]]
        , $match[0]
    );
}, $str);

echo $result;

输出

 I love <a title="a">[123]</a> and <a title="b">[124]</a> at <a title="XX">(456)</a>. I hate <a title="c">[234]</a> and <a title="d">[235]</a> at <a title="ZZ">(123)</a>.