How can I combine two (or more) preg_replace's - PHP

Viewed 85

< EDIT >

I Wanted to give a big thank you to all of you who have provided an answer, You have all given me great options. I will play with each and see which one suits my exact needs prior to selecting an answer. I do appreciate all of your responses though, everyone has a different approach to things. =)

bbcodes can (but not always do) include options, an example would be:

[URL="http://google.com"]GOOGLE[/URL]

</ EDIT >

I am currently hiding multiple variables from my string using the following method:

$result = preg_replace('/\[img\](.*)\[\/img\]/im', 'REPLACED', $qry);
$result = preg_replace('/\[url.*\](.*)\[\/url\]/im', 'REPLACED', $qry);

This works, but I would like to be able to do this with just one preg replace, and easily be able to add to it in the future if needed.

I have attempted to use:

$result = preg_replace("#\[/?(img|url)(=\s*\"?.*?\"?\s*)?]#im", 'REPLACED', $qry);

Which is only hiding the tags themselves.

How can I combine these replaces?

3 Answers

preg_replace function can take array of arguments. As an option, you could try with:

$find = ['/\[img\](.*)\[\/img\]/im', '/\[url.*\](.*)\[\/url\]/im'];
$replace = ['REPLACED', 'REPLACED'];

$result = preg_replace($find, $replace, $qry);

I think this way you will have some flexibility to have different replaced values

Your attempt is very close but you need to use a back reference to first capture group for closing match.

$result = preg_replace('~\[(img|url)\](.*)\[/\1\]~i', 'REPLACED', $qry);

Demo: https://3v4l.org/Ybvh2

The m modifier also has no functionality without an ^ or $. Perhaps you want the s modifier so the . extends to newlines? https://www.php.net/manual/en/reference.pcre.pattern.modifiers.php

I also would change the * quantifier to be non-greedy:

$result = preg_replace('~\[(img|url)\](.*?)\[/\1\]~is', 'REPLACED', $qry);

consider https://3v4l.org/8SdNd vs. https://3v4l.org/MC0pf (non greedied).

If you need to distinguish between images and URLs it is probably easiest to have 2 regexs. Functionality with 1 regex though can be achieved with preg_replace_callback:

$result = preg_replace_callback('~\[(img|url)\](.*?)\[/\1\]~is', function($match){
        return $match[1] =='url' ? 'REPLACED url' : 'REPLACED img';
        }, '[img]test[/img][not]img[/not][url]http][/url]');
echo $result;

You can use

preg_replace('~\[(img|url)\b[^]]*](.*?)\[/\1]~is', 'REPLACED', $qry);

The regex matches:

  • \[ - a [ char
  • (img|url) - Group 1: img or url
  • \b - a word boundary
  • [^]]* - 0 or more chars other than ]
  • ] - a ] char
  • (.*?) - Group 2: any zero or more chars, as few as possible
  • \[/\1] - [/, the same contents as in Group 1, and a ].

See the PHP demo:

$qry = '[url="google.com"]google[/url] and [img]image here[/img]';
echo preg_replace('~\[(img|url)\b[^]]*](.*?)\[/\1]~is', 'REPLACED', $qry);
// => REPLACED and REPLACED
Related