Я пытаюсь придумать следующую функцию, которая усекает строку к целым словам (если это возможно, иначе она должна усечь к символам):
function Text_Truncate($string, $limit, $more = '...')
{
$string = trim(html_entity_decode($string, ENT_QUOTES, 'UTF-8'));
if (strlen(utf8_decode($string)) > $limit)
{
$string = preg_replace('~^(.{1,' . intval($limit) . '})(?:\s.*|$)~su', '$1', $string);
if (strlen(utf8_decode($string)) > $limit)
{
$string = preg_replace('~^(.{' . intval($limit) . '}).*~su', '$1', $string);
}
$string .= $more;
}
return trim(htmlentities($string, ENT_QUOTES, 'UTF-8', true));
}
Вот некоторые тесты:
// Iñtërnâtiônàlizætiøn and then the quick brown fox... (49 + 3 chars)
echo dyd_Text_Truncate('Iñtërnâtiônàlizætiøn and then the quick brown fox jumped overly the lazy dog and one day the lazy dog humped the poor fox down until she died.', 50, '...');
// Iñtërnâtiônàlizætiøn_and_then_the_quick_brown_fox_... (50 + 3 chars)
echo dyd_Text_Truncate('Iñtërnâtiônàlizætiøn_and_then_the_quick_brown_fox_jumped_overly_the_lazy_dog and one day the lazy dog humped the poor fox down until she died.', 50, '...');
Они оба работают, как это, однако если я отбрасываю второе preg_replace()
Я получаю следующее:
Iñtërnâtiônàlizætiøn_and_then_the_quick_brown_fox_jumped_overly_the_lazy_dog и однажды лентяй горбил плохую лису вниз, пока она не умерла....
Я не могу использовать substr()
потому что это только работает на уровне байта, и у меня нет доступа к mb_substr()
ATM, я предпринял несколько попыток присоединиться к второму regex с первым, но без успеха.
Помогите S.M.S., я боролся с этим в течение почти часа.
Править: Я сожалею, я бодрствовал в течение 40 часов, и я бесстыдно пропустил это:
$string = preg_replace('~^(.{1,' . intval($limit) . '})(?:\s.*|$)?~su', '$1', $string);
Однако, если у кого-то есть более оптимизированный regex (или тот, который игнорирует конечный пробел), совместно используйте:
"Iñtërnâtiônàlizætiøn and then "
"Iñtërnâtiônàlizætiøn_and_then_"
РЕДАКТИРОВАНИЕ 2: Я все еще не могу избавиться от запаздывающего пробела, кто-то может выручить меня?
РЕДАКТИРОВАНИЕ 3: Хорошо, ни одно из моих редактирований действительно не работало, меня дурачил RegexBuddy - я должен, вероятно, оставить это другому дню и немного поспать теперь. Прочь на сегодняшний день.
Возможно, я смогу подарить вам счастливое утро после долгой ночи кошмаров RegExp:
'~^(.{1,' . intval($limit) . '}(?<=\S)(?=\s)|.{'.intval($limit).'}).*~su'
Сваривание:
^ # Start of String
( # begin capture group 1
.{1,x} # match 1 - x characters
(?<=\S)# lookbehind, match must end with non-whitespace
(?=\s) # lookahead, if the next char is whitespace, match
| # otherwise test this:
.{x} # got to x chars anyway.
) # end cap group
.* # match the rest of the string (since you were using replace)
Вы всегда можете добавить | $
в конец ( ? = \ s)
, но поскольку ваш код уже проверял, что длина строки превышает $ limit
, я не чувствовал, что этот случай будет необходим.
Думали ли вы о переносе слов? ( http://us3.php.net/wordwrap )