我有一个用PHP编写的代码片段,它从数据库中提取一个文本块,并将其发送到网页上的一个小部件。原文可以是一篇很长的文章,也可以是一两个短句;但是对于这个小部件,我不能显示超过200个字符。我可以使用substr()在200个字符处切断文本,但结果将在单词中间切断——我真正想要的是在200个字符前的最后一个单词的末尾切断文本。


当前回答

$shorttext = preg_replace('/^([\s\S]{1,200})[\s]+?[\s\S]+/', '$1', $fulltext);

描述:

^ -从字符串开头开始 ([\s\ s]{1200}) -从1到200的任意字符 [\ s] + ?-在短文本结尾不包含空格,这样我们就可以避免使用word…而不是word… [\s\ s]+ -匹配所有其他内容

测试:

让我们加上一些其他的r Regex101.com orrrr正好200个字符。 Regex101.com后第五r orrrrr排除。

享受。

其他回答

虽然这是一个相当老的问题,但我想我可以提供一个替代方案,因为它没有被提到,而且对PHP 4.3+有效。

您可以使用sprintf系列函数来截断文本,方法是使用%。ℕs精密修改器。

句号。后面跟着一个整数,它的含义取决于 说明符: 对于e, e, f和f说明符:这是小数点后要打印的位数(默认情况下,这是6)。 对于g和g说明符:这是要打印的有效数字的最大数量。 对于说明符:它作为一个截断点,设置字符串的最大字符限制

简单截断https://3v4l.org/QJDJU

$string = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
var_dump(sprintf('%.10s', $string));

结果

string(10) "0123456789"

扩展截断https://3v4l.org/FCD21

因为sprintf的功能类似于substr,并且会部分切断单词。下面的方法将通过使用strpos(wordwrap(…, '[break]'), '[break]'),并使用特殊的分隔符。这允许我们检索位置,并确保我们不匹配标准的句子结构。

返回不部分截断单词且不超过指定宽度的字符串,同时保留换行符(如果需要)。

function truncate($string, $width, $on = '[break]') {
    if (strlen($string) > $width && false !== ($p = strpos(wordwrap($string, $width, $on), $on))) {
        $string = sprintf('%.'. $p . 's', $string);
    }
    return $string;
}
var_dump(truncate('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ', 20));

var_dump(truncate("Lorem Ipsum is simply dummy text of the printing and typesetting industry.", 20));

var_dump(truncate("Lorem Ipsum\nis simply dummy text of the printing and typesetting industry.", 20));

结果

/* 
string(36) "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"  
string(14) "Lorem Ipsum is" 
string(14) "Lorem Ipsum
is" 
*/

使用wordwrap($string, $width)或strtok(wordwrap($string, $width), "\n")的结果

/*
string(14) "Lorem Ipsum is"
string(11) "Lorem Ipsum"
*/

也许这能帮助到一些人:

<?php

    $string = "Your line of text";
    $spl = preg_match("/([, \.\d\-''\"\"_()]*\w+[, \.\d\-''\"\"_()]*){50}/", $string, $matches);
    if (isset($matches[0])) {
        $matches[0] .= "...";
        echo "<br />" . $matches[0];
    } else {
        echo "<br />" . $string;
    }

?>

基于@Justin Poliey的正则表达式:

// Trim very long text to 120 characters. Add an ellipsis if the text is trimmed.
if(strlen($very_long_text) > 120) {
  $matches = array();
  preg_match("/^(.{1,120})[\s]/i", $very_long_text, $matches);
  $trimmed_text = $matches[0]. '...';
}

找到这个问题的完美解决方案是多么棘手,这令人惊讶。我还没有在本页上找到至少在某些情况下不会失败的答案(特别是如果字符串包含换行符或制表符,或者如果单词break不是空格,或者如果字符串有UTF-8多字节字符)。

这里有一个简单的解决方案,适用于所有情况。这里也有类似的答案,但是如果希望它处理多行输入,“s”修饰符很重要,而“u”修饰符使它正确地计算UTF-8多字节字符。

function wholeWordTruncate($s, $characterCount) 
{
    if (preg_match("/^.{1,$characterCount}\b/su", $s, $match)) return $match[0];
    return $s;
}

一个可能的边缘情况是…如果字符串的第一个$characterCount字符中没有任何空格,它将返回整个字符串。如果你喜欢在$characterCount处强制中断,即使它不是一个单词边界,你可以使用这个:

function wholeWordTruncate($s, $characterCount) 
{
    if (preg_match("/^.{1,$characterCount}\b/su", $s, $match)) return $match[0];
    return mb_substr($return, 0, $characterCount);
}

最后一个选项,如果你想让它添加省略号如果它截断字符串…

function wholeWordTruncate($s, $characterCount, $addEllipsis = ' …') 
{
    $return = $s;
    if (preg_match("/^.{1,$characterCount}\b/su", $s, $match)) 
        $return = $match[0];
    else
        $return = mb_substr($return, 0, $characterCount);
    if (strlen($s) > strlen($return)) $return .= $addEllipsis;
    return $return;
}

这将返回单词的前200个字符:

preg_replace('/\s+?(\S+)?$/', '', substr($string, 0, 201));