199

PHPで記述されたコードスニペットがあり、データベースからテキストのブロックを取得して、それをWebページのウィジェットに送信します。元のテキストブロックは、長い記事でも短い文でもかまいません。ただし、このウィジェットの場合、たとえば200文字を超える文字を表示することはできません。substr()を使用して200文字でテキストを切り落とすことができますが、結果は単語の途中で切り取られます。本当に必要なのは、200文字の前の最後の単語の最後でテキストを切り落とすことです。

4

31 に答える 31

237

ワードラップ機能を使用する。最大幅が指定した幅になるようにテキストを複数行に分割し、単語の境界で分割します。分割した後、最初の行を取得するだけです。

substr($string, 0, strpos(wordwrap($string, $your_desired_width), "\n"));

このワンライナーが処理しないことの1つは、テキスト自体が目的の幅よりも短い場合です。このエッジケースを処理するには、次のようなことを行う必要があります。

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文字は処理されません。正規表現の最後に「u」を追加して処理します。

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

于 2008-09-17T04:27:34.970 に答える
144

これは、単語の最初の 200 文字を返します。

preg_replace('/\s+?(\S+)?$/', '', substr($string, 0, 201));
于 2008-09-17T04:41:34.390 に答える
50
$WidgetText = substr($string, 0, strrpos(substr($string, 0, 200), ' '));

これで、文字列の最大長を超えずに、任意の文字列を最も近い単語全体に切り捨てる信頼性の高い方法が得られました。

上記の他の例を試しましたが、望ましい結果が得られませんでした。

于 2011-01-12T04:29:50.643 に答える
40

次の解決策は、 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.
于 2013-07-25T08:10:31.117 に答える
9

中国語や日本語などの一部の言語では単語の分割にスペース文字が使用されないため、「単語」で分割する場合は常に注意してください。また、悪意のあるユーザーは、スペースを入れずにテキストを入力したり、標準のスペース文字に似た Unicode を使用したりする可能性があります。この場合、どのソリューションを使用してもテキスト全体が表示される可能性があります。これを回避する方法は、通常どおりスペースで分割した後に文字列の長さを確認し、文字列がまだ異常な制限 (この場合は 225 文字) を超えている場合は、先に進み、その制限で愚かに分割することです。

非 ASCII 文字に関しては、このようなことに関するもう 1 つの警告があります。それらを含む文字列は、PHP の標準 strlen() によって、実際よりも長いと解釈されることがあります。strlen()/substr() 関数を使用して文字列を分割すると、文字の途中で文字列が分割される可能性があります! 疑わしい場合は、mb_strlen() / mb_substr()の方がもう少し確実です。

于 2008-09-17T06:08:57.707 に答える
8

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文字以降の最初のスペースで文字列が切り捨てられます。

于 2008-09-17T04:29:46.603 に答える
7

どうぞ:

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;
   }
}
于 2008-09-17T04:31:26.867 に答える
5

これは、@ Cd-MaN のアプローチに基づく私の関数です。

function shorten($string, $width) {
  if(strlen($string) > $width) {
    $string = wordwrap($string, $width);
    $string = substr($string, 0, strpos($string, "\n"));
  }

  return $string;
}
于 2010-03-26T12:36:03.183 に答える
5
$shorttext = preg_replace('/^([\s\S]{1,200})[\s]+?[\s\S]+/', '$1', $fulltext);

説明:

  • ^- 文字列の先頭から開始
  • ([\s\S]{1,200})- 任意のキャラクターを 1 から 200 まで獲得
  • [\s]+?- 短いテキストの末尾にスペースを含めないword ...でください。word...
  • [\s\S]+- 他のすべてのコンテンツに一致

テスト:

  1. regex101.comor他のいくつかに追加しましょうr
  2. regex101.com orrrrちょうど200文字。
  3. regex101.com5回目以降r orrrrrは除外。

楽しみ。

于 2014-07-03T15:04:13.963 に答える
2

必要なのは非常に単純な式なので、これを行うには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);
于 2008-09-17T04:33:57.420 に答える
2

これは、mattmac の回答に対する小さな修正です。

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

唯一の違いは、$string の末尾にスペースを追加することです。これにより、ReX357 のコメントのように最後の単語が途切れることがなくなります。

これをコメントとして追加するのに十分な担当者がいません。

于 2011-11-09T22:29:11.407 に答える
2
/*
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、スペース、タブ、キャリッジ リターン、ライン フィードなどの空白文字に一致する定義済みの文字クラスを使用します。

2 番目のパラメーター – 入力文字列 2 番目のパラメーターは、分割する長いテキスト文字列です。

3 番目のパラメーター – 制限 3 番目のパラメーターは、返される部分文字列の数を指定します。制限を に設定するとn、preg_split は n 要素の配列を返します。最初のn-1要素には部分文字列が含まれます。最後の(n th)要素には、残りの文字列が含まれます。

于 2012-04-05T09:32:56.550 に答える
2

わかりましたので、上記の回答に基づいてこれの別のバージョンを取得しましたが、より多くのことを考慮して (utf-8、\n および   ; )、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;
  }
于 2011-10-26T14:37:56.980 に答える
1

これが私がやった方法です:

$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")));
于 2014-12-11T10:33:32.263 に答える
1

@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]. '...';
}
于 2010-12-09T16:28:08.740 に答える
0

@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 よりも短い場合があります。

于 2015-06-24T15:03:34.273 に答える
0

私はこれが古いことを知っていますが...

function _truncate($str, $limit) {
    if(strlen($str) < $limit)
        return $str;
    $uid = uniqid();
    return array_shift(explode($uid, wordwrap($str, $limit, $uid)));
}
于 2013-02-26T12:48:07.903 に答える
0

私はこれがうまくいくと思います:

function 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 . "&nbsp;...";
    }
    else {
        $abbreviated_string = $string;
    }
    return $abbreviated_string;
}

バッファーを使用すると、返される文字列の長さを調整できます。

于 2018-05-11T11:00:25.630 に答える
-1

以前これを使っていた

<?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;
?>
于 2014-02-09T13:24:07.727 に答える
-2

ここでこれを試すことができます

substr( $str, 0, strpos($str, ' ', 200) ); 
于 2015-08-26T12:46:05.160 に答える