我正在尝试用preg_replace包装给定列表中的单词和单词序列。它几乎可以工作,但有一些用例它没有,我无法弄清楚如何。
例如我这样做:
// sort by descending length
usort($this->_keywords, function($a,$b){return(strlen($a)<strlen($b));});
// wrapper is -%string%-
foreach ($this->_keywords as $keyword) {
$value = preg_replace('/((?!-)' . $keyword . '(?!-))/i', str_replace('%string%', '\1', $this->_wrapper), $value);
}
从此关键字列表:
我想导致:
-Lorem - -ipsum - dolor -sit amet - , 奉献精神。 Phasellus rhoncus venenatis orci sed porta。桑达 非dolor色情。马塞德赛马场 -sit amet - nulla egestas facilisis。信用评级机构 fringilla,leo ac ullamcorper semper, urna eros pretium lectus,nec rhoncus ligula risus eu velit。 Nulla eu dapibus magna。 Sed vehicula tristique lacinia。 Maecenas tincidunt metus at urna consequat nec congue libero iaculis。 Nulla facilisi。 Phasellus -sed - sem ut risus mattis accumsan eu -sed enim - 即可。 Pellentesque居民morbi tristique senectus et netus et malesuada fames ac turpis egestas。 Suspendisse id est velit,eu cursus 华富嘉洛。 Vivamus lacinia euismod pretium。
有什么想法吗?
答案 0 :(得分:1)
最简单的方法是使用preg_replace_callback()
,并匹配已经包装的单词和每个关键字。当匹配是一个已被包装的单词时,只需将其修改即可。不需要有问题的环视。
function compare_length($a, $b) {
return strlen($a) < strlen($b);
}
function build_regex($keywords) {
usort($keywords, 'compare_length');
$pieces []= '/(?<wrapped>-[\w\s]*-)|(?<keyword>';
for ($i = 0; $i < count($pieces); $i++) {
if ($i > 0) $pieces []= '|';
$pieces []= preg_quote($keywords[$i], '/');
}
$pieces []= ')/';
return implode("", $pieces);
}
function wrap_callback($match) {
if (!empty($match['wrapped'])) {
return $match['wrapped'];
}
return "-{$match['wrapped']}-";
}
function wrap($text, $keywords) {
$regex = build_regex($keywords);
return preg_replace_callback($regex, 'wrap_callback');
}
答案 1 :(得分:0)
我最终通过使用对应于单词边界的\b
元字符解决了我的问题。
public function filter($value)
{
usort($this->_keywords, function($a,$b){return(strlen($a)<strlen($b));});
foreach ($this->_keywords as $keyword) {
$value = preg_replace(
'/((?<!-)('.$keyword.'\b)(?!\-))/i',
str_replace('%string%', '\2', $this->_wrapper) . '\3',
$value
);
}
return $value;
}