PHP通过在x个字符后的最后一个空格处截断字符串来摘录

时间:2018-08-31 11:35:24

标签: php

如果字符串长度超过110个字符,我会尝试从长文本中摘录,同时删除最后一个空格之后的所有内容。

        $string = 'Стихи похожи на людей: помнят прошлое и ничего не знают о будущем, хотят жить вечно, a страница уже перелистывается.';

        if (mb_strlen($string ) > 110) {
            $pos = mb_strpos($string , ' ', 110);
            $excerpt = rtrim(mb_substr($string, 0, $pos), '.,—-_!@\'"()*#~').'...';
        }

如果我使用print_r(mb_strlen($pos));打印,则$pos的结果为0,如果我将$pos更改为$pos = mb_strpos($quote_content, ' ', 99);,则其工作正常。

在这种情况下,最后一个单词的长度为16个字符,而整个字符串的长度为116个字符,因此对于为什么使用99偏移而上面的任何内容将产生{{1} }而不是摘录,而是返回$pos(基于当前示例)。

我这里有很多字符串长度和单词长度不同的字符串,因此我需要一种在所有情况下都可以使用的动态解决方案。有任何想法吗?

3 个答案:

答案 0 :(得分:1)

使用preg_replace将字符串切成固定数量的字符的简单(快速)方法是:

$string = 'Стихи похожи на людей: помнят прошлое и ничего не знают о будущем, хотят жить вечно, a страница уже перелистывается.';
$excerpt = preg_replace('/^(.{1,110})\s.*$/u', '$1...', $string);
echo $excerpt;

输出:

Стихи похожи на людей: помнят прошлое и ничего не знают о будущем, хотят жить вечно, a страница уже...

正则表达式的工作原理是从字符串的开头一直到空格字符为止,寻找^(.{1,110})\s个字符(从1到110)。由于量词是贪婪的,因此它需要尽可能多的字符。这些字符被分组捕获。然后,字符串的其余部分由.*$匹配,整个字符串被第一个捕获组和三个.'s$1...)替换,仅给出所需的第一部分。正则表达式上的u标志表示它将正确计数unicode字符。要调整摘录的长度,只需将110更改为所需的长度即可。

Regex101 demo

修改

还可以通过修改正则表达式,使其坚持捕获组的最后一个字符为{{1,从而删除所有非单词字符(因此您不会以the quick brown fox,...结尾) }}字符,然后允许以下字符成为非单词字符:

word

输出:

$string = 'Стихи похожи на людей: помнят прошлое и ничего не знают о будущем, хотят жить вечно, a страница уже перелистывается.';
$excerpt = preg_replace('/^(.{1,23}\w)\W.*$/u', '$1...', $string);
echo $excerpt;

Updated demo

答案 1 :(得分:1)

这将在最后一个空格处剪切字符串而不会剪切单词:

$excerpt = mb_substr($string, 0, mb_strrpos($string, ' ', -(mb_strlen($string) - 110)));

strrposmb_strrpos向后移动,因此您可以搜索从给定位置开始的最后一次出现

答案 2 :(得分:0)

通过检查110中的所有字符直到找到空间来进行懒惰修复

    // lazy fix by checking all chars from 110 until space was found

    if (mb_strlen($string) > 110) {
        $p = 110;
        while(!($pos = mb_strpos($string , ' ', $p--))){};
        $excerpt = rtrim(mb_substr($string, 0, $pos), '.,—-_!@\'"()*#~') . ' ... ';
    }