Kelimenin karakter belirli sayıda yakın PHP bir dize kesecek nasıl?

16 Cevap php

Ben bir veritabanından bir metin bloğu çeker ve bir web sayfasında bir widget dışarı gönderir PHP ile yazılmış bir kod parçası var. Metnin orijinal blok uzun bir makale ya da bir kısa cümle veya iki olabilir; ama bu widget için ben 200 karakter, diyelim ki, daha fazla gösteremez. Ben 200 karakter de metni kesmek için () substr kullanabilirsiniz, ama sonuç kelimelerin ortasında kesilmesi olacağını - ben gerçekten ne istiyorum son {sonunda metni doğrayın için [(0)] } 200 karakter önce.

16 Cevap

wordwrap işlevini kullanarak. Bu maksimum genişlik kelime sınırları kırma, belirttiğiniz biridir şekilde birden çok satır metinleri böler. Sonra bölme, sadece ilk satırı almak:

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

Metnin kendisi istenilen genişlikte daha kısa olduğunda bu oneliner ele vermez Bir şey böyledir. Bu kenar-durumda işlemek için, bir gibi bir şey yapmalıyım:

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

Yukarıdaki çözüm, gerçek kesim noktası önce, yeni satır içeriyorsa, zamanından önce metni kesme sorunu vardır. İşte bu sorunu çözen bir versiyonu:

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

Ayrıca, burada uygulanması test etmek için kullanılan PHPUnit TestClass olduğunu:

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

Justin Poliey en regex @ dayanarak:

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

Bu mattmac cevabı için küçük bir düzeltme:

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

Tek fark, $ string sonunda bir boşluk eklemek için. Bu son sözü ReX357 yorumuna göre kesilmiş değil sağlar.

Ben bir yorum olarak bu eklemek için yeterli rep puanı yok.

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

Kullanımı:

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

Bu irade çıktı ilk 10 kelime.

preg_split function alt dizeleri bir dize bölmek için kullanılır. Dize Bölünecek olan boyunca sınırları, normal ifadeler deseni kullanılarak belirtilir.

preg_split fonksiyon 4 parametre alır, ama sadece ilk 3 şu anda bizim için önemli olan.

First Parameter – Pattern The first parameter is the regular expressions pattern along which the string is to be split. In our case, we want to split the string across word boundaries. Therefore we use a predefined character class \s which matches white space characters such as space, tab, carriage return and line feed.

Second Parameter – Input String The second parameter is the long text string which we want to split.

Third Parameter – Limit The third parameter specifies the number of substrings which should be returned. If you set the limit to n, preg_split will return an array of n elements. The first n-1 elements will contain the substrings. The last (n th) element will contain the rest of the string.

Ben bu eski olduğunu biliyorum, ama ...

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

Ben daha önce kullanılan bu

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

Bu birisi yardımcı olacaktır olabilir:

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

?>

Bu kelimelerin ilk 200 karakter dönecektir:

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

Ve onu var - en yakın tam kelime için herhangi bir dize kesiliyor güvenilir bir yöntem, en fazla dize uzunluğu altında kalırken.

Yukarıda örneklerini de denedim ve istenen sonuçları vermedi.

Strpos ve substr kullanın:

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

Bu size 30 karakterden sonra ilk boşlukta kesilmiş bir dize verecektir.

Eğer bölme konum zaman "kelime" tarafından akılda tutmak gibi Çince ve Japonca gibi bazı dillerin kelimeleri bölmek için bir boşluk karakteri kullanmayın herhangi bir yerde bu. Ayrıca, kötü niyetli bir kullanıcının basitçe herhangi bir boşluk olmadan metin girmek, veya kullanarak olabilecek bazı Unicode benzerin kullandığınız herhangi bir çözüm zaten tüm metin görüntüleme sona erebilir bu durumda standart boşluk karakterine. Bu etrafında bir yolu normal alanlar üzerinde ayrıldıktan sonra dize uzunluğunu kontrol etmek olabilir, daha sonra, dize anormal bir limitin üstünde hala varsa - bu durumda belki 225 karakter - önde gidiyor ve o limitte dumbly bölme.

Bu gibi şeyler bir daha ihtar olmayan ASCII karakter geliyor; tek bir karakter yerine, sadece bir, iki ya da daha fazla bayt sürebilir, çünkü bunları içeren dizeleri, artık onlar gerçekten daha olarak PHP'nin standart strlen () tarafından yorumlanabilir. Sadece dizeleri bölmek için strlen () / substr () işlevlerini kullanarak, bir karakterin ortasında bir dize bölmek olabilir! Şüphe, mb_strlen() / mb_substr() biraz daha kusursuz zaman.

İşte @ Cd-adamın yaklaşımına dayalı benim işlevdir.

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

  return $string;
}

I wordwrap fonksiyonu $ mola parametre fark ettik zaman aşağıdaki çözüm doğdu:

string wordwrap ( string $str [, int $width = 75 [, string $break = "\n" [, bool $cut = false ]]] )

İşte the solution:

/**
 * 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 current(explode("\n", wordwrap($str, $width, "...\n")));
}

Example #1.

print truncate("This is very long string with many chars.", 25);

Yukarıdaki örneğin çıktısı:

This is very long string...

Example #2.

print truncate("This is short string.", 25);

Yukarıdaki örneğin çıktısı:

This is short string.

Buyrun:

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

Ne istediğinizi oldukça basit bir ifade olarak ben, bunu yapmak için preg_match fonksiyonunu kullanmak istiyorsunuz.

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

Ifadesi "bir boşluk ile biter uzunluğu 1-200 başından itibaren herhangi altdize maç" anlamına gelir. Sonuç $ sonucu ve maç $ maçta olduğunu. Bu özellikle herhangi bir alan üzerinde bitmeyen orijinal soruya ilgilenir. Eğer satırsonlarının sona yapmak istiyorsanız, için düzenli ifade değiştirin:

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

Tamam ben yukarıdaki cevaplara göre bu başka bir versiyonu var ama hesap daha fazla şeyler (utf-8 \ n ve & nbsp;) alarak wp ile kullanıldığında, aynı zamanda wordpress shortcodes sıyırma bir çizgi yorumladı.

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