我需要能够用一种BBcode样式元素包含的字符串替换字符串,但前提是该字符串尚未包含在元素中。
示例:
狐狸通过苏丹跑得非常快,但在[国家]加拿大[/ country]
运行得非常快
循环浏览我要替换的所有国家/地区的列表并将其包装在此国家/地区括号中我尝试了这个
$replace = preg_replace("#(?<!\[country(.)\])". preq_quote($country) ."(?!\[/country\])#", "[country]{$country}[/country]", $replace);
预期产出:
狐狸在[国家]苏丹[国家]运行得非常快,但在[国家]加拿大[/ country]
运行得非常快
但我真的得到了
实际输出:
狐狸在[国家]苏丹[国家]运行得非常快,但通过[国家] [国家]加拿大[/ country] [/ country]
运行得非常快
如果它已经被包裹了,我不想重新包裹它。
答案 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} } (白色字符或不是点的标点字符)