preg_replace php需要替换一个尚未包含在元素中的字符串

时间:2014-05-28 23:00:40

标签: php regex

我需要能够用一种BBcode样式元素包含的字符串替换字符串,但前提是该字符串尚未包含在元素中。

示例:

  

狐狸通过苏丹跑得非常快,但在[国家]加拿大[/ country]

运行得非常快

循环浏览我要替换的所有国家/地区的列表并将其包装在此国家/地区括号中我尝试了这个

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

预期产出:

  

狐狸在[国家]苏丹[国家]运行得非常快,但在[国家]加拿大[/ country]

运行得非常快

但我真的得到了

实际输出:

  

狐狸在[国家]苏丹[国家]运行得非常快,但通过[国家] [国家]加拿大[/ country] [/ country]

运行得非常快

如果它已经被包裹了,我不想重新包裹它。

1 个答案:

答案 0 :(得分:1)

这很简单,您可以使用(*SKIP)(*FAIL)技巧跳过字符串中的所有内容:

$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)禁止在模式稍后失败时重试子字符串,(*FAIL)强制正则表达式引擎失败。

注意:如果您确定国家/地区列表仅包含字母和空格,则无需使用preg_quote。但是,如果您的列表包含像R.D.C这样的abbr。 (“RépubliqueDémocratiqueduCongo”),最好使用preg_quote。要小心,如果列表\b中有abbr将不再有效,则必须用其他类型的边界替换它(因为点不在\w中),例如:{{1} } (白色字符或不是点的标点字符)