我有一个用PHP编写的代码片段,它从数据库中提取一个文本块,并将其发送到网页上的一个小部件。原文可以是一篇很长的文章,也可以是一两个短句;但是对于这个小部件,我不能显示超过200个字符。我可以使用substr()在200个字符处切断文本,但结果将在单词中间切断——我真正想要的是在200个字符前的最后一个单词的末尾切断文本。
当前回答
这是一个小修复mattmac的答案:
preg_replace('/\s+?(\S+)?$/', '', substr($string . ' ', 0, 201));
唯一的区别是在$string的末尾添加一个空格。这确保了最后一个词不会像ReX357的注释那样被切断。
我没有足够的代表点添加这作为一个评论。
其他回答
虽然这是一个相当老的问题,但我想我可以提供一个替代方案,因为它没有被提到,而且对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"
*/
当我注意到wordwrap函数的$break参数时,产生了以下解决方案:
字符串$str [, int $width = 75[,字符串$break = "\n" [, bool $cut = false]])
下面是解决方案:
/**
* Truncates the given string at the specified length.
*
* @param string $str The input string.
* @param int $width The number of chars at which the string will be truncated.
* @return string
*/
function truncate($str, $width) {
return strtok(wordwrap($str, $width, "...\n"), "\n");
}
示例# 1。
print truncate("This is very long string with many chars.", 25);
上面的例子将输出:
This is very long string...
例# 2。
print truncate("This is short string.", 25);
上面的例子将输出:
This is short string.
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);
}
我是这样做的:
$string = "I appreciate your service & idea to provide the branded toys at a fair rent price. This is really a wonderful to watch the kid not just playing with variety of toys but learning faster compare to the other kids who are not using the BooksandBeyond service. We wish you all the best";
print_r(substr($string, 0, strpos(wordwrap($string, 250), "\n")));
通过使用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);
推荐文章
- Printf与std::字符串?
- 不区分大小写的“in”
- 原则-如何打印出真正的sql,而不仅仅是准备好的语句?
- 如何从关联PHP数组中获得第一项?
- 我如何得到一个字符串的前n个字符而不检查大小或出界?
- PHP/MySQL插入一行然后获取id
- 我如何排序一个多维数组在PHP
- 如何在PHP中截断字符串最接近于一定数量的字符?
- PHP错误:“zip扩展名和unzip命令都没有,跳过。”
- Nginx提供下载。php文件,而不是执行它们
- Json_encode()转义正斜杠
- 如何在PHP中捕获cURL错误
- Ruby数组到字符串的转换
- 为什么在Java和。net中不能修改字符串?
- 如何要求一个分叉与作曲家?