Я пытаюсь придумать следующую функцию, которая усекает строку до целых слов (если возможно, в противном случае она должна усекать до символов):
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()
, я сделал несколько попыток присоединиться к второму регулярному выражению с первым, но без успеха.
Пожалуйста, помогите SMS, я боролся с этим почти час.
EDIT: Извините, я проспал в течение 40 часов, и я бесстыдно пропустил это:
$string = preg_replace('~^(.{1,' . intval($limit) . '})(?:\s.*|$)?~su', '$1', $string);
Тем не менее, если у кого-то есть более оптимизированное регулярное выражение (или то, которое игнорирует конечное пространство), разделите:
"Iñtërnâtiônàlizætiøn and then " "Iñtërnâtiônàlizætiøn_and_then_"
EDIT 2: я до сих пор не могу избавиться от отстающих пробелов, может кто-то мне помочь?
EDIT 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
, я не считаю, что этот случай был бы необходим.
Считаете ли вы использование wordwrap? ( http://us3.php.net/wordwrap )