La fusión de dos expresiones regulares para Palabras Truncar en Cuerdas
Pregunta
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):
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í hay 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 me cae el segundo preg_replace()
consigo 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 se puede utilizar substr()
ya que sólo funciona en nivel de byte y no tienen acceso a mb_substr()
ATM, he hecho varios intentos para unirse a la segunda expresión regular con el primero, 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 echado de menos esto:
$string = preg_replace('~^(.{1,' . intval($limit) . '})(?:\s.*|$)?~su', '$1', $string);
Sin 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 puedo deshacerme del espacio en blanco final, alguien me puede ayuda a cabo
Datos 3: De acuerdo, ninguno de mis ediciones hizo realmente el trabajo, que estaba siendo engañado por RegexBuddy - probablemente debería dejar esta tarea a otro día y dormir un poco. Off para hoy.
Solución
Tal vez le puede dar una mañana feliz después de una larga 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 desde su código ya estaba comprobando que la longitud de la cadena era más larga que la $limit
, no sentí ese caso sería NECESARIO.
Otros consejos
Ha considerado el uso de ajuste de línea? ( http://us3.php.net/wordwrap )