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

StackOverflow https://stackoverflow.com/questions/2682861

Вопрос

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

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, я борюсь с этим почти час.


Редактировать: Извините, я не проснулся 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, Я не чувствовал, что дело будет необходимым.

Другие советы

Вы думали, используя WordWrap? (http://us3.php.net/wordwrap)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top