array - php string truncate



如何截斷PHP中的字符串到最接近特定字符數的單詞? (17)

令人驚訝的是找到解決這個問題的完美解決方案有多棘手。 至少在某些情況下,我還沒有在這個頁面上找到一個不會失敗的答案(特別是如果字符串包含換行符或製表符,或者單詞break是空格以外的任何內容,或者該字符串具有UTF- 8個多字節字符)。

這是一個適用於所有情況的簡單解決方案。 這裡有類似的答案,但是如果你希望它使用多行輸入,並且“u”修飾符可以正確評估UTF-8多字節字符,那麼“s”修飾符就很重要。

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;
}

我有一個用PHP編寫的代碼片段,它從數據庫中提取一段文本並將其發送到網頁上的小部件。 原始文本塊可以是冗長的文章或簡短的一兩句; 但對於這個小部件,我不能顯示超過200個字符。 我可以使用substr()在200個字符處截斷文本,但結果會在文字中間切斷 - 我真正想要的是在200個字符之前的最後一個單詞的末尾處截斷文本。


Answer #1

使用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個字符後的第一個空格處截斷一個字符串。


Answer #2

在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);
}

Answer #3

在這裡你可以試試這個

substr( $str, 0, strpos($str, ' ', 200) ); 

Answer #4

好吧,我根據上面的答案得到了另一個版本,但考慮到了更多的事情(utf-8,\ n和&nbsp;),並且刪除了wordpress shortcodes的一行,如果與wp一起使用,則會進行評論。

function neatest_trim($content, $chars) 
  if (strlen($content) > $chars) 
  {
    $content = str_replace('&nbsp;', ' ', $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;
  }

Answer #5

幹得好:

function neat_trim($str, $n, $delim='…') {
   $len = strlen($str);
   if ($len > $n) {
       preg_match('/(.{' . $n . '}.*?)\b/', $str, $matches);
       return rtrim($matches[1]) . $delim;
   }
   else {
       return $str;
   }
}

Answer #6

我創建了一個更類似於substr的函數,並使用了@Dave的思想。

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);
}

Ps .:全長剪輯可能小於substr。


Answer #7

我會使用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);

Answer #8

我相信這是最簡單的方法:

$lines = explode('♦♣♠',wordwrap($string, $length, '♦♣♠'));
$newstring = $lines[0] . ' &bull; &bull; &bull;';

我正在使用特殊字符來分割文本並將其剪下。


Answer #9

我知道這是舊的,但是...

function _truncate($str, $limit) {
    if(strlen($str) < $limit)
        return $str;
    $uid = uniqid();
    return array_shift(explode($uid, wordwrap($str, $limit, $uid)));
}

Answer #10

當我注意到wordwrap函數的$ break參數時,下面的解決方案誕生了:

string stringwrap(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.

Answer #11

請記住,無論何時,某些語言(如中文和日語)不使用空格字符來拆分單詞時,只要用“單詞”分開即可。 此外,惡意用戶可以簡單地輸入文本而不用任何空格,或者使用與標準空格字符相似的Unicode,在這種情況下,您使用的任何解決方案都可能最終顯示整個文本。 解決這個問題的方法可能是檢查字符串長度,然後如果字符串仍然超出一個異常限制(在這種情況下可能是225個字符),然後繼續前進,並在該限制處將其分開。

談到非ASCII字符時,還要注意這類事情; 包含它們的字符串可能被PHP的標準strlen()解釋為比實際更長,因為單個字符可能需要兩個或更多字節而不是一個字節。 如果您只是使用strlen()/ substr()函數來拆分字符串,則可以在字符中間拆分字符串! 如果有疑問, mb_strlen() / mb_substr()會更簡單一些。


Answer #12

這是mattmac答案的一個小修復:

preg_replace('/\s+?(\S+)?$/', '', substr($string . ' ', 0, 201));

唯一的區別是在$ string的末尾添加一個空格。 這可以確保根據ReX357的評論不會切斷最後一個單詞。

我沒有足夠的代表點將其添加為評論。


Answer #13

這是我做到的:

$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")));

Answer #14

通過使用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'來處理它:

$parts = preg_split('/([\s\n\r]+)/u', $string, null, PREG_SPLIT_DELIM_CAPTURE);


Answer #15
$WidgetText = substr($string, 0, strrpos(substr($string, 0, 200), ' '));

在那裡你有它 - 一個可靠的方法截斷任何字符串到最近的整個單詞,而保持在最大字符串長度。

我試過上面的其他例子,但他們沒有產生預期的結果。


Answer #16
/*
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)元素將包含字符串的其餘部分。





function