2012-09-23 6 views
5

Ejemplo cadena de entrada: test:)test:)test:) :) test:p test
cadena de salida deseada: test :) test :) test :) :) test :p test¿Cómo agregar espacios alrededor de una subcadena si aún no hay espacios?

Como se puede ver en el ejemplo anterior, quiero analizar la cadena y producir una cadena de salida con espacios añadidos alrededor de todos los códigos de emoticonos predefinidos.

Estaba tratando de hacer esto con un par de bucles, pero al final no funcionó al 100% como se esperaba y fue terriblemente lento en documentos grandes.

Así que me pregunto cuál sería la mejor y más eficiente manera de hacer este tipo de análisis con PHP?

+5

expresiones regulares. aprendelas, disfrútalas y descubre que es realmente fácil hacerlo en una línea de 'preg_replace' – Prinzhorn

+0

Intenté hacer esto con preg_replace() antes, pero no funcionó por algún motivo. ¿Podrías ayudarme aquí? – Erik

+0

@Prinzhorn Probé con '$ text = preg_replace ('/([^]): \\) ([^])/i ',' $ 1 :) $ 2 ', $ text)' pero no funciona. ¿Alguna idea de lo que está mal con eso? – Erik

Respuesta

0

expresión en lugar regularmente puede utilizar str_replace función. función de PHP str_replace puede recibir arrays como parámetros, por lo que puede probar esto:

$input = 'test:)test:)test:) :) test:p test'; 
$smileys = array(':)', ':p'); 
$smileys_with_spaces = array(' :)', ' :p'); 
$output = str_replace($smileys_with_spaces, $smileys, $input); // test:) :) -> test:):) 
$output = str_replace($smileys, $smileys_with_spaces, $input); // test:):) -> test :) :) 
+0

Esto no parece una solución utilizable porque agregará espacios excesivos. Por ejemplo, agregará espacios a los códigos de emoticones que ya tienen espacios a su alrededor. – Erik

+0

Las expresiones regulares son una mejor manera. @xdazz dio una solución más apropiada. – doktorgradus

+0

Simplemente elimine los espacios sobrantes por 'str_replace ('', '', $ input);'. – doktorgradus

0

Probar:

$str = "test:)test:)test:) :) test:p test"; 
$str = preg_replace('/(?<=[a-z])(?=[^a-z\s])|(?<=[^a-z]{2})(?=[a-z])/', ' ', $str); 
+0

Éste no funcionará cuando dos códigos de smiley estén uno al lado del otro. Entonces, con $ str siendo ":) :)", no agrega ningún espacio – Erik

+0

@Erik ¿Está arreglado el patrón? – xdazz

0

actualización con soporte para N emoticonos

$smile = array(':)', ':p'); 

//Escape smiley chars for use in rx 
foreach($smile as &$s) { 
    $s = preg_quote($s, '/'); 
}unset($s); 

$rx = implode('|', $smile); 

$str = 'test:)test:)test:) :) test:p test'; 

$str = preg_replace('/ *('.$rx.') */', ' $1 ', $str); 
$str = preg_replace('/('.$rx.') +/', '$1 ', $str); 

echo $str; 
+0

Este funciona, excepto que agregará demasiados espacios si dos códigos de smiley están uno al lado del otro. por ejemplo ":) :)" se convertiría en " :) :) " mientras necesito ":) :)" en este ejemplo. – Erik

+0

alguna idea de cómo podría arreglar eso? – Erik

+0

Esta actualización aún no arregla espacios excesivos al principio o al final de la cadena. Y no puedo usar trim() porque si el original tiene espacios al principio o al final, debe permanecer así. – Erik

2

sustitución anidada:

preg_replace("/\s\s+/", " ", 
    str_replace(Array(":)", ":p"), 
     Array(" :) ", " :p "), $str)); 
0

Si también quieren no tienen espacios adicionales al inicio/final, intente esto:

$str = ':):)test:)test:)test:) :) test:p:) test'; 
$codes = array(
    ':)', ':p', // Add smileys here. 
); 

// We build the $regexp automatically 
$regexp = array(); 
foreach($codes as $smiley) 
    $regexp[] = preg_quote($smiley, '#'); 
$regexp = implode('|', $regexp); 
// Afterwards, we might replace the above with $regexp = 'VERYCOMPLICATEDSYNTAX'; 

// Split the string at smileys, trimming the smileys as we go, 
// and returning an array of smiley-and-non-smiley parts, except for empty ones 
$parts = preg_split("#\s*($regexp)\s*#", $str, -1, 
    PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE); 

// The new delimiter is a single space. 
$str = implode(' ', $parts); 

Tenga en cuenta que he utilizado el espacio en blanco de coincidencias \s lugar de un espacio literal; esto puede tener resultados no deseados si tiene avances de línea en la cadena original. Si ese es el caso, reemplace "\s" con un "" espacio literal.

0

Debe haber una solución más elegante, pero el código de abajo debería funcionar

$patterns = array(); 
$replacements = array(); 

$str = ':) test :)test:) test :)'; 

$smileys = array(':)', ':p'); 

foreach($smileys as &$s) { 
    $s = preg_quote($s, '/'); 
}unset($s); 
$escaped_smiley = implode('|', $smileys); 

$patterns[] = '/([^\s])('.$escaped_smiley.')([^\s])/'; // no spaces 
$patterns[] = '/([\s])('.$escaped_smiley.')([^\s])/'; // space on left 
$patterns[] = '/([^\s])('.$escaped_smiley.')([\s])/'; // space on right 

$patterns[] = '/^('.$escaped_smiley.')([\s])/'; // line starting, space succeding 
$patterns[] = '/^('.$escaped_smiley.')([^\s])/'; // line starting, no space 
$patterns[] = '/([\s])('.$escaped_smiley.')$/'; // line ending, space preceeding 
$patterns[] = '/([^\s])('.$escaped_smiley.')$/'; // line ending, no space 

$replacements[] = '$1 $2 $3'; // no spaces 
$replacements[] = '$1$2 $3'; // space on left 
$replacements[] = '$1 $2$3'; // space on right 

$replacements[] = ' $1$2'; // line starting 
$replacements[] = ' $1 $2'; // line starting 
$replacements[] = '$1$2 '; // line ending 
$replacements[] = '$1 $2 '; // line ending 


$result = preg_replace($patterns, $replacements, $str); 
echo str_replace(' ', '^', $result); 

[Editado con el código tomado de @Prinzhorn]

+0

Esto falla una cadena de entrada como ':) prueba:) prueba:) prueba :)' – Erik

+0

la salida es:) prueba :) prueba :) prueba :) ... observe los espacios faltantes al final del primer código de emoticón y antes del último. – Erik

+0

@Erik editó el código para tener en cuenta el comienzo y el final de la línea. También eliminó el bucle 'foreach' con' implode' y reemplazó los emoticonos citados con el comillas 'foreach' loop, de @Prinzhorn. – air4x

0

Si no se ha resuelto el problema, sin embargo, se me ocurrió con una solución que puede funcionar Primero explota la cuerda con los espacios como delimitadores, reemplaza los emoticones con espacios adicionales y repítalos con implosión.

Compruebe php fiddle para la implementación.

1
<?php 

$lspace = str_replace(":"," :","test:)test:)test:) :) test:p"); 
$rspace = str_replace(")",") ",$lspace); 
$out = preg_replace("/\s\s+/"," ",$rspace); 


echo $out; 
?> 

de salida: test :) test :) test :) :) test :p

Cuestiones relacionadas