2010-04-21 9 views
7

Estoy tratando de llegar a la siguiente función que trunca la cadena de palabras enteras (si es posible, de lo contrario, debe truncar caracteres):La fusión de dos expresiones regulares para truncar palabras en Cuerdas

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)); 
} 

Aquí están algunas pruebas:

// 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, '...'); 

ambos trabajan como es, sin embargo, si se me cae el segundo preg_replace() me sale el siguiente:

Iñtërnâtiônàlizætiøn_and_then_the_quick_brown_fox_jumped_overly_the_lazy_dog y un día el perro perezoso joroba del pobre zorro abajo hasta que murió ....

no puedo usar substr(), ya que sólo funciona en nivel de byte y no tienen acceso a mb_substr() ATM, he intentado varias veces unirme a la segunda expresión regular con la primera pero sin éxito.

Por favor, ayuda S.M.S., He estado luchando con esto durante casi una hora.


EDIT: Lo siento, he estado despierto durante 40 horas y sin vergüenza perdido esto:

$string = preg_replace('~^(.{1,' . intval($limit) . '})(?:\s.*|$)?~su', '$1', $string); 

embargo, si alguien tiene una expresión regular más optimizada (o uno que ignora el espacio final) Por favor comparta:

"Iñtërnâtiônàlizætiøn and then " 
"Iñtërnâtiônàlizætiøn_and_then_" 

EDIT 2: todavía no puede deshacerse de la espacios en blanco finales, alguien me puede ayudar?

EDIT 3: Bueno, ninguna de mis ediciones realmente funcionó, estaba siendo engañado por RegexBuddy - probablemente debería dejar esto para otro día y dormir un poco ahora. Desactivado por hoy.

+3

Pobre zorro. _____ – kennytm

+0

¿Por qué no usas 'trim' para deshacerte de los espacios en blanco al final? – Jens

+3

Despierta durante 40 horas y trata con expresiones regulares. +1 voto de compasión. –

Respuesta

3

Tal vez pueda darle una feliz mañana después de una noche de pesadillas RegExp:

'~^(.{1,' . intval($limit) . '}(?<=\S)(?=\s)|.{'.intval($limit).'}).*~su' 

ebullición abajo:

^  # 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) 

Siempre se puede añadir el |$ hasta el final de (?=\s) pero dado que su código ya estaba verificando que la longitud de la cadena era más larga que $limit, no sentí que el caso fuera necesario.

+0

Más una "tarde feliz" pero gracias gnarf! Me dormí con la impresión de que tendría que usar el método de búsqueda anticipada o simplemente usar 'trim()'. ¡Gracias de nuevo! –

Cuestiones relacionadas