it-swarm-ko.tech

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

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

173
Brian

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

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

이 oneliner가 처리하지 않는 한 가지는 텍스트 자체가 원하는 너비보다 짧은 경우입니다. 이 Edge 사례를 처리하려면 다음과 같은 작업을 수행해야합니다.

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

214
Grey Panther

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

preg_replace('/\s+?(\S+)?$/', '', substr($string, 0, 201));
133
mattmac
$WidgetText = substr($string, 0, strrpos(substr($string, 0, 200), ' '));

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

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

43
Dave

다음 해결책은 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.
34
Sergiy Sokolenko

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

비 ASCII 문자와 관련하여 이와 같은 사항에 한 가지 더주의해야합니다. PHP의 표준 strlen ()은이를 포함하는 문자열을 실제보다 더 긴 것으로 해석 할 수 있습니다. 단일 문자는 하나가 아닌 2 바이트 이상을 차지할 수 있기 때문입니다. strlen ()/substr () 함수를 사용하여 문자열을 분할하는 경우 문자 중간에 문자열을 분할 할 수 있습니다! 의심 스러울 경우 mb_strlen () / mb_substr () 는 조금 더 무모합니다.

9
Garrett Albright

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 자 뒤에 첫 공백에서 잘린 문자열이 제공됩니다.

8
Lucas Oman

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

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

  return $string;
}
5
Camsoft

여기 있습니다 :

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

이 문제에 대한 완벽한 해결책을 찾는 것이 얼마나 까다로운 지 놀랍습니다. 나는이 페이지에서 적어도 일부 상황에서 실패하지 않는 대답을 찾지 못했습니다 (특히 문자열에 줄 바꿈이나 탭이 있거나 단어 나누기가 공백이 아닌 경우 또는 문자열에 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 문자에 공백이 없으면 전체 문자열을 반환합니다. Word 경계가 아닌 경우에도 $ 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;
}
3
orrd
_$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.comorrrr 정확히 200 자입니다.
  3. regex101.com 5 번째 이후 rorrrrr 제외되었습니다.

즐겨.

3
hlcs

위의 답변을 기반으로 다른 버전을 얻었지만 더 많은 것을 고려하고 (utf-8,\n 및 & nbsp;) 또한 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;
  }
2
Yo-L
/*
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 개만 관련이 있습니다.

첫 번째 매개 변수 – 패턴 첫 번째 매개 변수는 문자열을 분할 할 정규식 패턴입니다. 이 경우 문자열을 Word 경계에 걸쳐 분할하려고합니다. 따라서 공백, 탭, 캐리지 리턴 및 줄 바꿈과 같은 공백 문자와 일치하는 사전 정의 된 문자 클래스 \s를 사용합니다.

두 번째 매개 변수 – 입력 문자열 두 번째 매개 변수는 분할하려는 긴 텍스트 문자열입니다.

세 번째 매개 변수 – 제한 세 번째 매개 변수는 반환해야하는 하위 문자열 수를 지정합니다. 한계를 n로 설정하면 preg_split은 n 개의 요소 배열을 반환합니다. 첫 번째 n-1 요소에는 하위 문자열이 포함됩니다. 마지막 (n th) 요소는 나머지 문자열을 포함합니다.

2
bodi0

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);
2
Justin Poliey

이것이 내가 한 방법입니다.

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

나는 당신이 원하는 것을 거의하는 기능을 가지고 있습니다. 몇 가지 편집을하면 정확하게 맞을 것입니다 :

<?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;
}
?>
1
Rikudou_Sennin

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

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

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

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

이것을 의견으로 추가 할 담당자가 충분하지 않습니다.

1
tanc

공백없이 문자열을 처리하기 위해 DaveAmalMurali 의 코드에 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);
}
0
jdorenbush

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

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

나는 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보다 작을 수 있습니다.

0
evandro777

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

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

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

0
Namida

나는 이것을 전에 사용했다

<?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;
?>
0
Yousef Altaf

나는 이것이 효과가 있음을 발견했다.

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

}

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

0
Mat Barnett

이것을 사용하십시오 :

다음 코드는 ','를 제거합니다. 다른 문자 또는 하위 문자열이 있으면 ','대신 사용할 수 있습니다.

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

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

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