[php] PHP에서 문자열을 특정 문자 수에 가장 가까운 단어로 자르는 방법은 무엇입니까?

데이터베이스에서 텍스트 블록을 가져 와서 웹 페이지의 위젯으로 보내는 PHP로 작성된 코드 스 니펫이 있습니다. 원본 텍스트 블록은 긴 기사 나 짧은 문장 또는 두 문장 일 수 있습니다. 그러나이 위젯의 ​​경우 200 자 이상을 표시 할 수 없습니다. substr ()을 사용하여 200 자로 텍스트를자를 수 있지만 결과는 단어 중간에서 잘릴 수 있습니다. 실제로 원하는 것은 200 자 전에 마지막 단어 의 끝에서 텍스트를 자르는 것 입니다.



답변

워드 랩 기능 을 사용합니다 . 텍스트를 여러 줄로 분할하여 최대 너비가 지정한 너비로 단어 경계를 어기도록합니다. 분할 후 간단히 첫 번째 줄을 가져옵니다.

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


답변

단어의 처음 200자를 반환합니다.

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


답변

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

그리고 최대 문자열 길이를 유지하면서 문자열을 가장 가까운 전체 단어로 자르는 신뢰할 수있는 방법입니다.

위의 다른 예제를 시도했지만 원하는 결과를 얻지 못했습니다.


답변

다음 솔루션은 wordwrap 함수 의 $ break 매개 변수를 발견했을 때 탄생했습니다 .

문자열 줄 바꿈 (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.


답변

중국어 및 일본어와 같은 일부 언어는 공백 문자를 사용하여 단어를 나누지 않는 “단어”로 분할 할 때마다 유의하십시오. 또한 악의적 인 사용자는 공백없이 텍스트를 입력하거나 표준 공백 문자와 비슷한 유니 코드를 사용하여 텍스트를 입력 할 수 있습니다.이 경우 사용하는 솔루션이 전체 텍스트를 표시 할 수 있습니다. 이 문제를 해결하는 방법은 문자열을 공백으로 분할 한 후 문자열 길이를 확인한 다음 문자열이 여전히 비정상적인 제한 (이 경우 225 자) 이상인 경우 계속 진행하여 그 한계에서 바보로 분할하는 것입니다.

비 ASCII 문자와 관련하여 이와 같은 사항에 한 가지 더주의해야합니다. PHP의 표준 strlen ()에 의해 포함 된 문자열은 실제보다 더 긴 것으로 해석 될 수 있습니다. 단일 문자는 하나가 아닌 2 바이트 이상을 차지할 수 있기 때문입니다. 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 자 뒤에 첫 공백에서 잘린 문자열이 제공됩니다.


답변

여기 있습니다 :

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