Let's start right away with an example:

$str = "[[Яша|ya.ru]] qwerty [[Яков|yandex.ru]]"; $str = preg_replace('/\[\[(.*?)\|(.*?)\]\]/','<a href="$2" target="_blank">$1</a>',$str); echo $str; 

The string $ str I accept from the user.
In principle, the code above works, but no verification is performed.
How can you affect the found $ 1 and $ 2 in the preg_replace before they are used?

Maybe I did not go well, and there is a better solution, I will be glad to hear.

  • Duck, do not replace, find matches, process, then make the desired result string. This is exactly the behavior you want to implement, or not? - teran
  • 2
    or preg_replace_callback() - teran
  • one
    @borodatych " (How can you affect the found $ 1 and $ 2) " - in preg_replace () not, but in preg_replace_callback (), as mentioned above. In general, it is necessary to "influence" the pattern of a regular expression, as you create it, this result will be found. - Edward
  • one
    @teran, thanks for the tip, quite suitable. If you set an example, even a plus, if you wish. - borodatych
  • 3
    @borodatych is a similar example with preg_replace_callback () - Edward

2 answers 2

To handle captured values ​​during replacement, you can use the preg_replace_callback function. It is used when it is necessary to perform any actions with captured offsets before inserting them into the modified drain.

An example of code that replaces words based on an associated array and converts domain names to uppercase:

 $str = '[[Яша|ya.ru]] qwerty [[Яков|yandex.ru]]'; $dict = ['Яша' => 'Яков', 'Яков' => 'Яша']; // Словарь для замены имён $res = []; // Массив для найденных имён echo preg_replace_callback( '~\[\[(.*?)\|(.*?)]]~', function ($m) use ($dict, &$res) { // $m - объект совпадения, $m[0] - всё совпадение, $m[1] - значение первой группы и т.д. array_push($res, $m[1]); // Добавление в массив найденных имён return '<a href="'. mb_strtoupper($m[2]) . // Значение группы №2 в верхний регистр '" target="_blank">'. (isset($dict[$m[1]]) ? $dict[$m[1]] : $m[1]) . // Замена имени из словаря, если имеется '</a>'; }, $str ) . "\n"; print_r($res); // Вывод найденных имён 

Result:

 <a href="YA.RU" target="_blank">Яков</a> qwerty <a href="YANDEX.RU" target="_blank">Яша</a> Array ( [0] => Яша [1] => Яков ) 

Pay attention to use ($dict, &$res) : $dict can be used only for reading, and &$res - for reading and writing (thanks to & ).

    My option, not without the help of @teran:

     $str = "[[Яша|ya.ru]] qwerty [[Яков|yandex.ru]]"; $str = preg_replace_callback('~\[\[(.*?)\|(.*?)]]~',function ($m){ $link = htmlspecialchars(strip_tags($m[2])); $text = htmlspecialchars(strip_tags($m[1])); if( strpos($link,'http')===FALSE ) $link = "http://$link"; return '<a href="'. $link .'" target="_blank" class="solid">'. $text .'</a>'; },$str); echo $str;