如何包装尚未包装的单词或单词序列?

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 元素中?

Android 的换行小部件布局

溢出包装不会破坏动态添加的 div 上的单词

按单词包装 UILabel 并以编程方式扩展 UITableViewCell 高度

如何序列化/反序列化IList集合的类包装器?