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

StackOverflow https://stackoverflow.com/questions/79960

  •  09-06-2019
  •  | 
  •  

문제

데이터베이스에서 텍스트 블록을 가져와서 웹페이지의 위젯으로 보내는 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), ' '));

그리고 거기에 최대 문자열 길이를 유지하면서 문자열을 가장 가까운 전체 단어로 자르는 안정적인 방법이 있습니다.

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

$break 매개변수를 발견했을 때 다음 솔루션이 탄생했습니다. 줄 바꿈 기능:

문자열 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.

중국어 및 일본어와 같은 일부 언어에서는 단어를 분할하는 데 공백 문자를 사용하지 않는다는 점을 "단어"로 분할할 때마다 명심하세요.또한 악의적인 사용자가 공백 없이 텍스트를 입력하거나 표준 공백 문자와 유사한 유니코드를 사용할 수도 있습니다. 이 경우 사용하는 솔루션은 어쨌든 전체 텍스트를 표시하게 될 수 있습니다.이 문제를 해결하는 방법은 정상적으로 공백으로 분할한 후 문자열 길이를 확인하는 것입니다. 그런 다음 문자열이 여전히 비정상적인 제한(이 경우 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자 이후 첫 번째 공백이 잘린 문자열이 제공됩니다.

@Cd-MaN의 접근 방식을 기반으로 한 기능은 다음과 같습니다.

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

  return $string;
}

여기 있습니다:

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

이 문제에 대한 완벽한 해결책을 찾는 것이 얼마나 까다로운지 놀랍습니다.나는 이 페이지에서 최소한 어떤 상황(특히 문자열에 줄바꿈이나 탭이 포함되어 있거나 단어 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;
}
$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.com 에 추가하자 or 다른 몇 가지 r
  2. regex101.com orrrr 정확히 200자.
  3. regex101.com 다섯 번째 이후 r orrrrr 제외된.

즐기다.

나는 이것을 하기 위해 preg_match 함수를 사용할 것입니다. 왜냐하면 당신이 원하는 것은 매우 간단한 표현이기 때문입니다.

$matches = array();
$result = preg_match("/^(.{1,199})[\s]/i", $text, $matches);

표현식은 "공간으로 끝나는 길이 1-200의 시작부터 시작하는 모든 기판과 일치합니다." 결과는 $ 결과를 얻었고 일치는 $ 일치합니다.이는 구체적으로 모든 공간에서 끝나는 원래 질문을 처리합니다.줄바꿈으로 끝내려면 정규식을 다음과 같이 변경하세요.

$result = preg_match("/^(.{1,199})[\n]/i", $text, $matches);

좋습니다. 위의 답변을 기반으로 다른 버전을 얻었지만 더 많은 사항을 고려했습니다(utf-8, 및  ), 또한 wp와 함께 사용되는 경우 주석 처리된 wordpress 단축 코드를 제거하는 줄입니다.

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;
  }
/*
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) 요소에는 나머지 문자열이 포함됩니다.

@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]. '...';
}

이것은 mattmac의 답변에 대한 작은 수정 사항입니다.

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

유일한 차이점은 $string 끝에 공백을 추가한다는 것입니다.이렇게 하면 ReX357의 설명에 따라 마지막 단어가 잘리지 않습니다.

이것을 코멘트로 추가하기에는 담당자 포인트가 충분하지 않습니다.

당신이 원하는 거의 모든 기능을 수행하는 기능이 있습니다. 몇 가지 편집을 수행하면 정확히 맞을 것입니다.

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

나는 이것이 오래되었다는 것을 알고 있지만 ...

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

예전에 이걸 사용했어요

<?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과 더 유사한 함수를 만들고 @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);
}

추신.:전체 길이 절단은 substr보다 작을 수 있습니다.

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

나는 이것이 가장 쉬운 방법이라고 생각합니다.

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

특수 문자를 사용하여 텍스트를 분할하고 잘라냅니다.

나는 이것이 효과가 있다고 생각합니다 :

함수 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;

}

버퍼를 사용하면 반환된 문자열의 길이를 조정할 수 있습니다.

이것을 사용하십시오:

다음 코드는 ','를 제거합니다.다른 문자나 하위 문자열이 있는 경우 ',' 대신 해당 문자나 하위 문자열을 사용할 수 있습니다.

substr($string, 0, strrpos(substr($string, 0, $comparingLength), ','))

// 다른 문자열 계정이 있는 경우

substr($string, 0, strrpos(substr($string, 0, $comparingLength-strlen($currentString)), ','))

여기에서 이것을 시도해 볼 수 있습니다

substr( $str, 0, strpos($str, ' ', 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;
    }

?>
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top