Слияние двух Регулярных выражений для Усечения Слов в Строках

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

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

7
задан Alix Axel 21 April 2010 в 13:44
поделиться

2 ответа

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

3
ответ дан 7 December 2019 в 16:40
поделиться

Думали ли вы о переносе слов? ( http://us3.php.net/wordwrap )

0
ответ дан 7 December 2019 в 16:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: