我有一个用PHP编写的代码片段,它从数据库中提取一个文本块,并将其发送到网页上的一个小部件。原文可以是一篇很长的文章,也可以是一两个短句;但是对于这个小部件,我不能显示超过200个字符。我可以使用substr()在200个字符处切断文本,但结果将在单词中间切断——我真正想要的是在200个字符前的最后一个单词的末尾切断文本。
当前回答
也许这能帮助到一些人:
<?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]. '...';
}
就我所知,这里所有的解只有在起点固定的情况下才有效。 允许你转动这个: 悲伤之神,神圣之神,痛苦之神,痛苦之神。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 ..."
运行代码。
你可以用这个:
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);
虽然这是一个相当老的问题,但我想我可以提供一个替代方案,因为它没有被提到,而且对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"
*/
下面是基于@Cd-MaN方法的函数。
function shorten($string, $width) {
if(strlen($string) > $width) {
$string = wordwrap($string, $width);
$string = substr($string, 0, strpos($string, "\n"));
}
return $string;
}
推荐文章
- Printf与std::字符串?
- 不区分大小写的“in”
- 原则-如何打印出真正的sql,而不仅仅是准备好的语句?
- 如何从关联PHP数组中获得第一项?
- 我如何得到一个字符串的前n个字符而不检查大小或出界?
- PHP/MySQL插入一行然后获取id
- 我如何排序一个多维数组在PHP
- 如何在PHP中截断字符串最接近于一定数量的字符?
- PHP错误:“zip扩展名和unzip命令都没有,跳过。”
- Nginx提供下载。php文件,而不是执行它们
- Json_encode()转义正斜杠
- 如何在PHP中捕获cURL错误
- Ruby数组到字符串的转换
- 为什么在Java和。net中不能修改字符串?
- 如何要求一个分叉与作曲家?