Agrus Agrus -4 years ago 104
PHP Question

Using preg_replace with career names and failing at it

I've got a list of careers and I'm trying to replace them with tags, for instance:

Coach -> <a href='whatever-file'>Coach<a/>

However, when a career such as "General Director" comes up, its replaced like this:

General <a href='whatever-file'>Director</a>

My array containing the patterns goes like this:

[0] => /\bDirector\b/i
[1] => /\bPresident\b/i
[2] => /\bGeneral Manager\b/i
[3] => /\bConstituency Aid\b/i
[4] => /\bData Input Clerk\b/i
[5] => /\bFront Desk Clerk\b/i
[6] => /\bGeneral Director\b/i
[7] => /\bPlanning Officer\b/i

And the replacements is:

[0] => <a href='#'Director</a>
[1] => <a href='#'President</a>
[2] => <a href='#'General Manager</a>
[3] => <a href='#'Constituency Aid</a>
[4] => <a href='#'Data Input Clerk</a>
[5] => <a href='#'Front Desk Clerk</a>
[6] => <a href='#'General Director</a>
[7] => <a href='#'Planning Officer</a>

my preg replace goes like this:

$subject = preg_replace($patterns, $replacements, $subject,1);

How can I prevent "Director" from replacing "General Director"?

Thanks in advance!

Answer Source

Update (wrapping found strings while adding link values to href)

You need to create a name-value array from your data, with the search words to be used as keys and replacements as values. Then, you need to sort the array by key length in descending order, and use the keys to build a dynamoc regex like the one in the original answer. To get the url data and paste it into the resulting string, you need to pass the array into a preg_replace_callback with the help of use keyword.

See the PHP online demo:

$words = array('General', 'Director','President','General Manager','Constituency Aid',
          'Data Input Clerk','Front Desk Clerk','General Director','Planning Officer');
$urls = array('general', 'director','president', 'general-manager ', 'consistency-aid',
           'data-input-clerk', 'front-desk-clerk', 'general-director', 'planning-officer');
$srch = array_combine($words, $urls);

uksort($srch, function($a, $b) {
    if (strlen($a) == strlen($b))
        return 0;
    if (strlen($a) < strlen($b))
        return 1;
    return -1;

$pattern= '/\b(?:' . implode("|", array_keys($srch)) . ')\b/i';
$s = "Meet our new General Director!";
echo preg_replace_callback($pattern, function($m) use ($srch) {
    return "<a href='" . $srch[$m[0]] . "'>" . $m[0] . "</a>";
}, $s);

Origignal answer (wrapping found strings only)

Use a simple preg_replace with the following code:

$words = array('Director','President','General Manager','Constituency Aid','Data Input Clerk','Front Desk Clerk','General Director','Planning Officer');
usort($words, function($a, $b) {
    return strlen($b) - strlen($a);
$pattern= '/\b(?:' . implode("|", $words) . ')\b/i';
$s = "Meet our new General Director!";
echo preg_replace($pattern, "<a href='#'>\$0</a>", $s);

See PHP demo


  • Declare the word array
  • Use usort part of code to sort the search words in a descending way by length (if General comes before General Director in the list, you will get General wrapped in a tag separately)
  • The /\b(?:alternative1|alternative2|...)\b/i regex will process all the non-overlapping matches in 1 pass
  • $0 backreference in the replacement pattern will insert the matched variant of the search term (if it is general director, it will use it, not General Director).
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download