我有一个用PHP编写的代码片段,可从数据库中提取文本块并将其发送到网页上的小部件。原始文本块可以是一篇冗长的文章或一两个简短的句子;但是对于此小部件,我最多只能显示200个字符。我可以使用substr()以200个字符的形式截断文本,但是结果是在单词中间截断-我真正想要的是在200个字符之前的最后一个单词的末尾截断文本。
s($str)->truncateSafely(200)
如在该独立库中所发现的,您可能会有所帮助。
我有一个用PHP编写的代码片段,可从数据库中提取文本块并将其发送到网页上的小部件。原始文本块可以是一篇冗长的文章或一两个简短的句子;但是对于此小部件,我最多只能显示200个字符。我可以使用substr()以200个字符的形式截断文本,但是结果是在单词中间截断-我真正想要的是在200个字符之前的最后一个单词的末尾截断文本。
s($str)->truncateSafely(200)
如在该独立库中所发现的,您可能会有所帮助。
Answers:
通过使用自动换行功能。它将文本分成多行,以使最大宽度为您指定的宽度,并在单词边界处断开。分割后,您只需走第一行:
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);
\n
在所需宽度之前有一个,这似乎会过早地剪切文本。
Arabic
字母,现在借助tokenTruncate
功能已将其简化为正确的单词。.tnx一百万:)
这将返回单词的前200个字符:
preg_replace('/\s+?(\S+)?$/', '', substr($string, 0, 201));
if (strlen($string) > $your_desired_width) { preg_replace(...); }
/\s+?(?:\S+)?$/
$WidgetText = substr($string, 0, strrpos(substr($string, 0, 200), ' '));
这样就可以了–一种可靠的方法,可以将任何字符串截断为最接近的整个单词,同时保持最大字符串长度为限。
我已经尝试了上面的其他示例,但它们未产生预期的结果。
if
声明中if (strlen($str) > 200) { ... }
$WidgetText = substr($string, 0, strpos($string, ' ', 200));
当我注意到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.
description
博客文章的a)
preg_replace('/\s+/', ' ', $description)
用一个空格替换所有空白字符;)
当您在某些语言(例如中文和日语)不使用空格字符来拆分单词的任何地方通过“单词”拆分时,请记住。此外,恶意用户可能只输入文本而没有任何空格,或者使用与标准空格字符相似的Unicode字符,在这种情况下,您使用的任何解决方案都可能最终仍然显示整个文本。解决此问题的一种方法可能是检查字符串长度,然后按正常方式在空格上进行分割,然后,如果字符串仍超出异常限制(在这种情况下可能为225个字符),则继续进行操作,并在该限制下进行双倍分割。
对于非ASCII字符,还要再做一个类似的说明。PHP的标准strlen()可能将包含它们的字符串解释为比实际长度更长,因为单个字符可能占用两个或更多字节,而不是一个字节。如果仅使用strlen()/ substr()函数拆分字符串,则可以在字符中间拆分字符串!不确定时,mb_strlen() / mb_substr()更加安全。
使用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个字符后的第一个空格处被截断。
$shorttext = preg_replace('/^([\s\S]{1,200})[\s]+?[\s\S]+/', '$1', $fulltext);
描述:
^
-从字符串开头([\s\S]{1,200})
-从1到200之间的任何字符[\s]+?
-在短文字的结尾不要包含空格,因此我们可以避免word ...
使用word...
[\s\S]+
-匹配所有其他内容测试:
regex101.com
让我们添加or
一些其他r
regex101.com
orrrr
正好200个字符。regex101.com
第五名之后被r
orrrrr
排除在外。请享用。
$1
是一个“替换”,但是在此特定上下文中,它指的是什么?一个空变量?
$1
引用以匹配括号内的内容([\s\S]{1,200})
。$2
如果有任何模式,将引用第二对第二对括号。
为这个问题找到完美的解决方案是多么棘手,这令人惊讶。我尚未在此页面上找到答案,至少在某些情况下不会失败(尤其是如果字符串包含换行符或制表符,或者单词break是空格以外的任何东西,或者字符串具有UTF- 8个多字节字符)。
这是一个适用于所有情况的简单解决方案。这里有类似的答案,但是如果您希望它与多行输入一起使用,则“ s”修饰符很重要,并且“ u”修饰符可使其正确评估UTF-8多字节字符。
function wholeWordTruncate($s, $characterCount)
{
if (preg_match("/^.{1,$characterCount}\b/su", $s, $match)) return $match[0];
return $s;
}
一个可能的边缘情况...如果字符串的前$ characterCount个字符根本没有空格,它将返回整个字符串。如果您希望它强制在$ characterCount处中断,即使它不是单词边界,也可以使用以下命令:
function wholeWordTruncate($s, $characterCount)
{
if (preg_match("/^.{1,$characterCount}\b/su", $s, $match)) return $match[0];
return mb_substr($return, 0, $characterCount);
}
最后一个选项,如果要截断字符串,请添加省略号...
function wholeWordTruncate($s, $characterCount, $addEllipsis = ' …')
{
$return = $s;
if (preg_match("/^.{1,$characterCount}\b/su", $s, $match))
$return = $match[0];
else
$return = mb_substr($return, 0, $characterCount);
if (strlen($s) > strlen($return)) $return .= $addEllipsis;
return $return;
}
我将使用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和&nbsp;),如果与wp一起使用,则还会删除注释掉的wordpress短代码。
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;
}
/*
Cut the string without breaking any words, UTF-8 aware
* param string $str The text string to split
* param integer $start The start position, defaults to 0
* param integer $words The number of words to extract, defaults to 15
*/
function wordCutString($str, $start = 0, $words = 15 ) {
$arr = preg_split("/[\s]+/", $str, $words+1);
$arr = array_slice($arr, $start, $words);
return join(' ', $arr);
}
用法:
$input = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna liqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.';
echo wordCutString($input, 0, 10);
这将输出前10个字。
该preg_split
函数用于将字符串拆分为子字符串。使用正则表达式模式指定要沿其分割字符串的边界。
preg_split
函数接受4个参数,但现在只有前3个与我们相关。
第一个参数-模式第一个参数是正则表达式模式,字符串将沿着该模式被分割。在我们的例子中,我们想将字符串跨单词边界分割。因此,我们使用预定义的字符类\s
来匹配空白字符,例如空格,制表符,回车符和换行符。
第二个参数-输入字符串第二个参数是我们要分割的长文本字符串。
第三个参数-限制第三个参数指定应返回的子字符串数。如果将限制设置为n
,则preg_split将返回n个元素的数组。第一个n-1
元素将包含子字符串。最后一个(n th)
元素将包含字符串的其余部分。
我有一个功能几乎可以满足您的要求,如果您要进行一些编辑,它将完全适合您:
<?php
function stripByWords($string,$length,$delimiter = '<br>') {
$words_array = explode(" ",$string);
$strlen = 0;
$return = '';
foreach($words_array as $word) {
$strlen += mb_strlen($word,'utf8');
$return .= $word." ";
if($strlen >= $length) {
$strlen = 0;
$return .= $delimiter;
}
}
return $return;
}
?>
这是我的方法:
$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")));
我使用@Dave的想法创建了一个更类似于substr的函数。
function substr_full_word($str, $start, $end){
$pos_ini = ($start == 0) ? $start : stripos(substr($str, $start, $end), ' ') + $start;
if(strlen($str) > $end){ $pos_end = strrpos(substr($str, 0, ($end + 1)), ' '); } // IF STRING SIZE IS LESSER THAN END
if(empty($pos_end)){ $pos_end = $end; } // FALLBACK
return substr($str, $pos_ini, $pos_end);
}
备注:全长切割可能小于substr。
在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);
}
我发现这可行:
函数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." ...";
}
else {
$abbreviated_string=$string;
}
return $abbreviated_string;
}
缓冲区允许您调整返回字符串的长度。
用这个:
以下代码将删除“,”。如果您还有其他字符或子字符串,则可以使用它代替“,”
substr($string, 0, strrpos(substr($string, 0, $comparingLength), ','))
//如果您还有另一个字符串帐户
substr($string, 0, strrpos(substr($string, 0, $comparingLength-strlen($currentString)), ','))
尽管这是一个相当老的问题,但我想我可以提供一个替代方法,因为它没有被提及并且对PHP 4.3+有效。
您可以sprintf
通过使用%.ℕs
precision修饰符使用函数系列来截断文本 。
句号
.
后跟整数的含义取决于说明符:
- 对于e,E,f和F指定符:这是小数点后要打印的位数(默认情况下为6)。
- 对于g和G指定符:这是要打印的最大有效位数。
- 对于s说明符:它充当截止点,为字符串设置最大字符数限制
$string = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
var_dump(sprintf('%.10s', $string));
结果
string(10) "0123456789"
由于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"
*/
我以前用过
<?php
$your_desired_width = 200;
$string = $var->content;
if (strlen($string) > $your_desired_width) {
$string = wordwrap($string, $your_desired_width);
$string = substr($string, 0, strpos($string, "\n")) . " More...";
}
echo $string;
?>
在这里你可以试试看
substr( $str, 0, strpos($str, ' ', 200) );