如何包装尚未包装的单词或单词序列?
Posted
技术标签:
【中文标题】如何包装尚未包装的单词或单词序列?【英文标题】:How to wrap words or words sequences which have not been already wrapped? 【发布时间】:2011-04-24 20:18:23 【问题描述】:我正在尝试使用 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);
来自这个关键字列表:
洛雷姆 ipsum 坐在一起 空 sed sed enim我想要结果:
-Lorem- -ipsum- dolor -sit amet-, consectetur adipiscing 精英。菜豆 rhoncus venenatis orci sed porta。赛德 非多洛厄洛斯。暂停马萨 -sit amet- nulla egestas facilisis。克拉斯 fringilla, leo ac ullamcorper semper, urna eros pretium lectus, nec rhoncus ligula risus eu velit。 Nulla eu 大皮布斯麦格纳。 sed vehicula tristique 拉西尼亚。 Maecenas tincidunt metus 在 urna consequat nec congue libero 伊库利斯。 Nulla facilisi。菜豆 -sed- sem ut risus mattis accumsan eu -sed 敌人-。 Pellentesque 居民 morbi tristique senectus et netus et malesuada 名声 ac turpis egestas。 Suspendisse id est velit, eu cursus 夸姆Vivamus lacinia euismod pretium。
有什么想法吗?
【问题讨论】:
您遇到的具体问题是什么? 【参考方案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');
【讨论】:
【参考方案2】:我终于通过使用对应于单词边界的\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;
【讨论】:
以上是关于如何包装尚未包装的单词或单词序列?的主要内容,如果未能解决你的问题,请参考以下文章
在 Angular 中,我如何动态地将某些单词包装在另一个 html 元素中?