我有一个用PHP编写的代码片段,它从数据库中提取一个文本块并将其发送到网页上的小部件.原始文本块可以是冗长的文章或短句或短句; 但对于这个小部件,我不能显示超过200个字符.我可以使用substr()来切断200个字符的文本,但结果会在单词中间切断 - 我真正想要的是在200个字符之前在最后一个单词的末尾剪切文本.
通过使用wordwrap功能.它将文本分成多行,使得最大宽度是您指定的宽度,在字边界处断开.拆分后,您只需占用第一行:
substr($string, 0, strpos(wordwrap($string, $your_desired_width), "\n"));
这个oneliner无法处理的一件事是文本本身短于所需宽度的情况.要处理这种边缘情况,应该做以下事情:
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'来处理它:
$parts = preg_split('/([\s\n\r]+)/u', $string, null, PREG_SPLIT_DELIM_CAPTURE);
这将返回单词的前200个字符:
preg_replace('/\s+?(\S+)?$/', '', substr($string, 0, 201));
$WidgetText = substr($string, 0, strrpos(substr($string, 0, 200), ' '));
而且你有它 - 一种可靠的方法,可以将任何字符串截断为最接近的整个单词,同时保持在最大字符串长度之下.
我尝试过上面的其他例子,但没有产生预期的结果.
当我注意到wordwrap函数的$ break参数时,出现了以下解决方案:
string wordwrap(string $ str [,int $ width = 75 [,string $ 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.
每当你在某些语言(例如中文和日文)不使用空格字符来分割单词时,请记住"单词".此外,恶意用户可以简单地输入没有任何空格的文本,或使用与标准空格字符类似的Unicode,在这种情况下,您使用的任何解决方案最终都可能最终显示整个文本.解决这个问题的方法可能是在正常分割空格后检查字符串长度,然后,如果字符串仍然高于异常限制 - 在这种情况下可能是225个字符 - 继续并在该限制下愚蠢地将其拆分.
对于非ASCII字符,还有一个需要注意的事情; 包含它们的字符串可能被PHP的标准strlen()解释为比它们实际上更长,因为单个字符可能需要两个或更多字节而不是一个字节.如果你只是使用strlen()/ substr()函数来分割字符串,你可以在字符的中间分割一个字符串!如果有疑问,mb_strlen()/mb_substr()更加万无一失.
使用strpos和substr:
这将为您提供在30个字符后第一个空格处截断的字符串.
7> Camsoft..:这是我的功能基于@ Cd-MaN的方法.
function shorten($string, $width) { if(strlen($string) > $width) { $string = wordwrap($string, $width); $string = substr($string, 0, strpos($string, "\n")); } return $string; }