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


当前回答

$WidgetText = substr($string, 0, strrpos(substr($string, 0, 200), ' '));

这样你就有了它——一种可靠的方法,可以将任何字符串截断为最近的整个单词,同时保持在最大字符串长度以下。

我尝试了上面的其他例子,它们没有产生预期的结果。

其他回答

通过使用wordwrap函数。它将文本分割成多行,这样最大宽度就是您指定的宽度,在单词边界处断开。分割之后,你只需取第一行:

substr($string, 0, strpos(wordwrap($string, $your_desired_width), "\n"));

这个线性程序不能处理的一件事是,当文本本身比所需的宽度短时。为了处理这种边情况,我们应该这样做:

if (strlen($string) > $your_desired_width) 
{
    $string = wordwrap($string, $your_desired_width);
    $string = substr($string, 0, strpos($string, "\n"));
}

上面的解决方案存在一个问题,即如果文本在实际切点之前包含换行符,则会过早地切割文本。这里有一个解决这个问题的版本:

function tokenTruncate($string, $your_desired_width) {
  $parts = preg_split('/([\s\n\r]+)/', $string, null, PREG_SPLIT_DELIM_CAPTURE);
  $parts_count = count($parts);

  $length = 0;
  $last_part = 0;
  for (; $last_part < $parts_count; ++$last_part) {
    $length += strlen($parts[$last_part]);
    if ($length > $your_desired_width) { break; }
  }

  return implode(array_slice($parts, 0, $last_part));
}

另外,这里是用于测试实现的PHPUnit测试类:

class TokenTruncateTest extends PHPUnit_Framework_TestCase {
  public function testBasic() {
    $this->assertEquals("1 3 5 7 9 ",
      tokenTruncate("1 3 5 7 9 11 14", 10));
  }

  public function testEmptyString() {
    $this->assertEquals("",
      tokenTruncate("", 10));
  }

  public function testShortString() {
    $this->assertEquals("1 3",
      tokenTruncate("1 3", 10));
  }

  public function testStringTooLong() {
    $this->assertEquals("",
      tokenTruncate("toooooooooooolooooong", 10));
  }

  public function testContainingNewline() {
    $this->assertEquals("1 3\n5 7 9 ",
      tokenTruncate("1 3\n5 7 9 11 14", 10));
  }
}

编辑:

像'à'这样的特殊UTF8字符不会被处理。在REGEX的末尾添加'u'来处理它:

部分美元= preg_split (' / ([\ s \ n \ r] +) / u ',美元字符串,null, PREG_SPLIT_DELIM_CAPTURE);

用这个:

下面的代码将删除','。如果你有任何其他字符或子字符串,你可以用它来代替','

substr($string, 0, strrpos(substr($string, 0, $comparingLength), ','))

//如果你有另一个字符串帐户

substr($string, 0, strrpos(substr($string, 0, $comparingLength-strlen($currentString)), ','))

Dave和AmalMurali的代码中添加了IF/ELSEIF语句,用于处理没有空格的字符串

if ((strpos($string, ' ') !== false) && (strlen($string) > 200)) { 
    $WidgetText = substr($string, 0, strrpos(substr($string, 0, 200), ' ')); 
} 
elseif (strlen($string) > 200) {
    $WidgetText = substr($string, 0, 200);
}

我发现这很有效:

function abbreviate_string_to_whole_word($string, $max_length, $buffer) {
    if (strlen($string) > $max_length) {
        $string_cropped = substr($string, 0, $max_length - $buffer);
        $last_space = strrpos($string_cropped, " ");
        if ($last_space > 0) {
            $string_cropped = substr($string_cropped, 0, $last_space);
        }
        $abbreviated_string = $string_cropped . "&nbsp;...";
    }
    else {
        $abbreviated_string = $string;
    }
    return $abbreviated_string;
}

缓冲区允许您调整返回字符串的长度。

使用strpos和substr:

<?php

$longString = "I have a code snippet written in PHP that pulls a block of text.";
$truncated = substr($longString,0,strpos($longString,' ',30));

echo $truncated;

这将为您提供一个在30个字符后的第一个空格处截断的字符串。