Kyle Browning
Kyle Browning

Reputation: 5382

preg_replace php need to replace a string not already wrapped in element

I need to be able to replace a string with what would be wrapped in a sort of BBcode style element, but only if that string is not already wrapped in the element.

Example:

The fox runs really fast through Sudan, but also runs really fast through [country]Canada[/country]

Loopping through a list of all the countries I want to replace and wrap in this country brackets I tried this

$replace = preg_replace("#(?<!\[country(.)\])". preq_quote($country) ."(?!\[/country\])#", "[country]{$country}[/country]", $replace);

Expected output:

The fox runs really fast through [country]Sudan[country], but also runs really fast through [country]Canada[/country]

But Im actually getting

Actual output:

The fox runs really fast through [country]Sudan[country], but also runs really fast through [country][country]Canada[/country][/country]

If its already wrapped, I dont want to re-wrap it.

Upvotes: 0

Views: 224

Answers (1)

Casimir et Hippolyte
Casimir et Hippolyte

Reputation: 89557

It's easy, you can use the (*SKIP)(*FAIL) trick to skip all that you want in a string:

$listOfCountries = array('France', 'Soudan', 'Quatar', 'China', 'Zimbabwe');

$pattern '~\[country][^[]+\[/country](*SKIP)(*FAIL)|\b(?i:'
       . implode('|', $listOfCountries) . ')\b~';

$result = preg_replace($pattern, '[country]$0[/country]', $text);

(*SKIP) forbids to retry a substring when the pattern fails later, and (*FAIL) forces the regex engine to fail.

Note: if you are sure that the list of countries only contains letters and spaces, you don't need to use preg_quote. However if your list contains abbr like R.D.C. ("République Démocratique du Congo"), it is better to use preg_quote. Be careful, if you have abbr in the list \b will no more work, you must replace it with an other kind of boundary (since the dot is not in \w), example:(?=\s|[^\PP.]) (a white character or a punctuation character that is not a dot)

Upvotes: 1

Related Questions