我有一个用PHP编写的代码片段,它从数据库中提取一个文本块,并将其发送到网页上的一个小部件。原文可以是一篇很长的文章,也可以是一两个短句;但是对于这个小部件,我不能显示超过200个字符。我可以使用substr()在200个字符处切断文本,但结果将在单词中间切断——我真正想要的是在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")));
其他回答
就我所知,这里所有的解只有在起点固定的情况下才有效。 允许你转动这个: 悲伤之神,神圣之神,痛苦之神,痛苦之神。Ut enim ad minim veniam。 到这个: 神圣的,神圣的… 如果想要截断一组特定关键字周围的单词,该怎么办?
截断一组特定关键字周围的文本。
我们的目标是能够转换这个:
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna liqua. Ut enim ad minim veniam.
到这个:
...consectetur adipisicing elit, sed do eiusmod tempor...
这是在显示搜索结果、摘要等时非常常见的情况。为了实现这一点,我们可以结合使用以下两种方法:
/**
* Return the index of the $haystack matching $needle,
* or NULL if there is no match.
*
* This function is case-insensitive
*
* @param string $needle
* @param array $haystack
* @return false|int
*/
function regexFindInArray(string $needle, array $haystack): ?int
{
for ($i = 0; $i < count($haystack); $i++) {
if (preg_match('/' . preg_quote($needle) . '/i', $haystack[$i]) === 1) {
return $i;
}
}
return null;
}
/**
* If the keyword is not present, it returns the maximum number of full
* words that the max number of characters provided by $maxLength allow,
* starting from the left.
*
* If the keyword is present, it adds words to both sides of the keyword
* keeping a balanace between the length of the suffix and the prefix.
*
* @param string $text
* @param string $keyword
* @param int $maxLength
* @param string $ellipsis
* @return string
*/
function truncateWordSurroundingsByLength(string $text, string $keyword,
int $maxLength, string $ellipsis): string
{
if (strlen($text) < $maxLength) {
return $text;
}
$pattern = '/' . '^(.*?)\s' .
'([^\s]*' . preg_quote($keyword) . '[^\s]*)' .
'\s(.*)$' . '/i';
preg_match($pattern, $text, $matches);
// break everything into words except the matching keywords,
// which can contain spaces
if (count($matches) == 4) {
$words = preg_split("/\s+/", $matches[1], -1, PREG_SPLIT_NO_EMPTY);
$words[] = $matches[2];
$words = array_merge($words,
preg_split("/\s+/", $matches[3], -1, PREG_SPLIT_NO_EMPTY));
} else {
$words = preg_split("/\s+/", $text, -1, PREG_SPLIT_NO_EMPTY);
}
// find the index of the matching word
$firstMatchingWordIndex = regexFindInArray($keyword, $words) ?? 0;
$length = false;
$prefixLength = $suffixLength = 0;
$prefixIndex = $firstMatchingWordIndex - 1;
$suffixIndex = $firstMatchingWordIndex + 1;
// Initialize the text with the matching word
$text = $words[$firstMatchingWordIndex];
while (($prefixIndex >= 0 or $suffixIndex <= count($words))
and strlen($text) < $maxLength and strlen($text) !== $length) {
$length = strlen($text);
if (isset($words[$prefixIndex])
and (strlen($text) + strlen($words[$prefixIndex]) <= $maxLength)
and ($prefixLength <= $suffixLength
or strlen($text) + strlen($words[$suffixIndex]) <= $maxLength)) {
$prefixLength += strlen($words[$prefixIndex]);
$text = $words[$prefixIndex] . ' ' . $text;
$prefixIndex--;
}
if (isset($words[$suffixIndex])
and (strlen($text) + strlen($words[$suffixIndex]) <= $maxLength)
and ($suffixLength <= $prefixLength
or strlen($text) + strlen($words[$prefixIndex]) <= $maxLength)) {
$suffixLength += strlen($words[$suffixIndex]);
$text = $text . ' ' . $words[$suffixIndex];
$suffixIndex++;
}
}
if ($prefixIndex > 0) {
$text = $ellipsis . ' ' . $text;
}
if ($suffixIndex < count($words)) {
$text = $text . ' ' . $ellipsis;
}
return $text;
}
现在你可以做:
$text = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do' .
'iusmod tempor incididunt ut labore et dolore magna liqua. Ut enim' .
'ad minim veniam.';
$text = truncateWordSurroundingsByLength($text, 'elit', 25, '...');
var_dump($text); // string(32) "... adipisicing elit, sed do ..."
运行代码。
我将使用preg_match函数来做到这一点,因为您想要的是一个相当简单的表达式。
$matches = array();
$result = preg_match("/^(.{1,199})[\s]/i", $text, $matches);
表达式的意思是“匹配从长度1-200开始以空格结尾的任何子字符串”。结果在$result中,匹配在$matches中。这就解决了你最初的问题,即以任意空格结束的问题。如果你想让它以换行符结束,将正则表达式更改为:
$result = preg_match("/^(.{1,199})[\n]/i", $text, $matches);
好吧,所以我得到了另一个版本的这个基于上面的答案,但考虑到更多的东西(utf-8, \n和 ),如果与wp一起使用,也是剥离wordpress shortcodes注释的行。
function neatest_trim($content, $chars)
if (strlen($content) > $chars)
{
$content = str_replace(' ', ' ', $content);
$content = str_replace("\n", '', $content);
// use with wordpress
//$content = strip_tags(strip_shortcodes(trim($content)));
$content = strip_tags(trim($content));
$content = preg_replace('/\s+?(\S+)?$/', '', mb_substr($content, 0, $chars));
$content = trim($content) . '...';
return $content;
}
下面是基于@Cd-MaN方法的函数。
function shorten($string, $width) {
if(strlen($string) > $width) {
$string = wordwrap($string, $width);
$string = substr($string, 0, strpos($string, "\n"));
}
return $string;
}
你可以用这个:
function word_shortener($text, $words=10, $sp='...'){
$all = explode(' ', $text);
$str = '';
$count = 1;
foreach($all as $key){
$str .= $key . ($count >= $words ? '' : ' ');
$count++;
if($count > $words){
break;
}
}
return $str . (count($all) <= $words ? '' : $sp);
}
例子:
word_shortener("Hello world, this is a text", 3); // Hello world, this...
word_shortener("Hello world, this is a text", 3, ''); // Hello world, this
word_shortener("Hello world, this is a text", 3, '[read more]'); // Hello world, this[read more]
Edit
工作原理:
1. 从输入文本中打开空格:
$all = explode(' ', $text);
例如,如果$text将是"Hello world",那么$all是一个带有爆炸值的数组:
“你好”,“世界”)
2. 对于每个单词:
选择展开文本中的每个元素:
foreach($all as $key){...
将当前单词($key)附加到$str,如果它是最后一个单词,则添加空格:
$str .= $key . ($count >= $words ? '' : ' ');
然后给$count加上1,检查它是否大于max limit($words)打破循环:
if($count > $words){
break;
}
只有当最终文本小于输入文本时,才返回$str和分隔符($sp):
return $str . (count($all) <= $words ? '' : $sp);
推荐文章
- Printf与std::字符串?
- 不区分大小写的“in”
- 原则-如何打印出真正的sql,而不仅仅是准备好的语句?
- 如何从关联PHP数组中获得第一项?
- 我如何得到一个字符串的前n个字符而不检查大小或出界?
- PHP/MySQL插入一行然后获取id
- 我如何排序一个多维数组在PHP
- 如何在PHP中截断字符串最接近于一定数量的字符?
- PHP错误:“zip扩展名和unzip命令都没有,跳过。”
- Nginx提供下载。php文件,而不是执行它们
- Json_encode()转义正斜杠
- 如何在PHP中捕获cURL错误
- Ruby数组到字符串的转换
- 为什么在Java和。net中不能修改字符串?
- 如何要求一个分叉与作曲家?