Объединение двух регулярных выражений для усечения слов в строках

Я пытаюсь придумать следующую функцию, которая усекает строку до целых слов (если возможно, в противном случае она должна усекать до символов):

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 – я должен, вероятно, оставить это на другой день и немного поспать. На сегодня.

Solutions Collecting From Web of "Объединение двух регулярных выражений для усечения слов в строках"

Возможно, я могу дать вам счастливое утро после долгой ночи кошмаров 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 )