Reemplace todos los caracteres que no sean letras ni números con un guión [duplicado]
Tengo un problema con las URL. Quiero poder convertir títulos que puedan contener cualquier cosa y quitarles todos los caracteres especiales para que solo tengan letras y números y, por supuesto, me gustaría reemplazar los espacios con guiones.
¿Cómo se haría esto? He oído mucho sobre el uso de expresiones regulares (regex)...
Esto debería hacer lo que estás buscando:
function clean($string) {
$string = str_replace(' ', '-', $string); // Replaces all spaces with hyphens.
return preg_replace('/[^A-Za-z0-9\-]/', '', $string); // Removes special chars.
}
Uso:
echo clean('a|"bc!@£de^&$f g');
Salida:abcdef-g
Editar:
Oye, solo una pregunta rápida: ¿cómo puedo evitar que haya varios guiones uno al lado del otro? ¿Y reemplazarlos con solo 1?
function clean($string) {
$string = str_replace(' ', '-', $string); // Replaces all spaces with hyphens.
$string = preg_replace('/[^A-Za-z0-9\-]/', '', $string); // Removes special chars.
return preg_replace('/-+/', '-', $string); // Replaces multiple hyphens with single one.
}
limpieza mejorada
La siguiente solución tiene una versión "más amigable con SEO":
function hyphenize($string) {
$dict = array(
"I'm" => "I am",
"thier" => "their",
// Add your own replacements here
);
return strtolower(
preg_replace(
array( '#[\\s-]+#', '#[^A-Za-z0-9. -]+#' ),
array( '-', '' ),
// the full cleanString() can be downloaded from http://www.unexpectedit.com/php/php-clean-string-of-utf8-chars-convert-to-similar-ascii-char
cleanString(
str_replace( // preg_replace can be used to support more complicated replacements
array_keys($dict),
array_values($dict),
urldecode($string)
)
)
)
);
}
function cleanString($text) {
$utf8 = array(
'/[áàâãªä]/u' => 'a',
'/[ÁÀÂÃÄ]/u' => 'A',
'/[ÍÌÎÏ]/u' => 'I',
'/[íìîï]/u' => 'i',
'/[éèêë]/u' => 'e',
'/[ÉÈÊË]/u' => 'E',
'/[óòôõºö]/u' => 'o',
'/[ÓÒÔÕÖ]/u' => 'O',
'/[úùûü]/u' => 'u',
'/[ÚÙÛÜ]/u' => 'U',
'/ç/' => 'c',
'/Ç/' => 'C',
'/ñ/' => 'n',
'/Ñ/' => 'N',
'/–/' => '-', // UTF-8 hyphen to "normal" hyphen
'/[’‘‹›‚]/u' => ' ', // Literally a single quote
'/[“”«»„]/u' => ' ', // Double quote
'/ /' => ' ', // nonbreaking space (equiv. to 0x160)
);
return preg_replace(array_keys($utf8), array_values($utf8), $text);
}
El fundamento de las funciones anteriores (que considero muy ineficientes; la siguiente es mejor) es que un servicio que no se nombrará aparentemente ejecutó revisiones ortográficas y reconocimiento de palabras clave en las URL.
Después de perder mucho tiempo con las paranoias de un cliente, descubrí que, después de todo, no estaban imaginando cosas: sus expertos en SEO [definitivamente no lo soy] informaron que, por ejemplo, convertir "Viaggi Economy Perù" en viaggi-economy-peru
"se comportó mejor" que viaggi-economy-per
( la "limpieza" anterior eliminó los caracteres UTF8; Bogotá se convirtió en bogot , Medellín se convirtió en medelln y así sucesivamente).
También hubo algunos errores ortográficos comunes que parecieron influir en los resultados, y la única explicación que tenía sentido para mí es que nuestra URL estaba siendo descomprimida, las palabras seleccionadas y utilizadas para impulsar Dios sabe qué algoritmos de clasificación. Y esos algoritmos aparentemente habían sido alimentados con cadenas limpiadas en UTF8, de modo que "Perù" se convirtió en "Perú" en lugar de "Per". "Per" no coincidía y en cierto modo lo tomó en el cuello.
Para mantener los caracteres UTF8 y reemplazar algunos errores ortográficos, la función más rápida a continuación se convirtió en la función más precisa (?) anterior. $dict
Por supuesto, hay que confeccionarlo a mano.
Respuesta anterior
Un enfoque sencillo:
// Remove all characters except A-Z, a-z, 0-9, dots, hyphens and spaces
// Note that the hyphen must go last not to be confused with a range (A-Z)
// and the dot, NOT being special (I know. My life was a lie), is NOT escaped
$str = preg_replace('/[^A-Za-z0-9. -]/', '', $str);
// Replace sequences of spaces with hyphen
$str = preg_replace('/ */', '-', $str);
// The above means "a space, followed by a space repeated zero or more times"
// (should be equivalent to / +/)
// You may also want to try this alternative:
$str = preg_replace('/\\s+/', '-', $str);
// where \s+ means "zero or more whitespaces" (a space is not necessarily the
// same as a whitespace) just to be sure and include everything
Tenga en cuenta que es posible que primero tenga que urldecode()
escribir la URL, ya que %20 y + son en realidad espacios. Quiero decir, si tiene "Never%20gonna%20give%20you%20up", querrá que se convierta en Never-gonna-give-you-. arriba, no Never20gonna20give20you20up . Puede que no lo necesites, pero pensé en mencionar la posibilidad.
Entonces la función terminada junto con los casos de prueba:
function hyphenize($string) {
return
## strtolower(
preg_replace(
array('#[\\s-]+#', '#[^A-Za-z0-9. -]+#'),
array('-', ''),
## cleanString(
urldecode($string)
## )
)
## )
;
}
print implode("\n", array_map(
function($s) {
return $s . ' becomes ' . hyphenize($s);
},
array(
'Never%20gonna%20give%20you%20up',
"I'm not the man I was",
"'Légeresse', dit sa majesté",
)));
Never%20gonna%20give%20you%20up becomes never-gonna-give-you-up
I'm not the man I was becomes im-not-the-man-I-was
'Légeresse', dit sa majesté becomes legeresse-dit-sa-majeste
Para manejar UTF-8 utilicé una cleanString
implementación que se encuentra en línea (enlace roto desde entonces, pero al comienzo de la respuesta hay una copia simplificada con todos los caracteres UTF8 no demasiado esotéricos; también es fácil agregarle más caracteres si need) que convierte caracteres UTF8 en caracteres normales, preservando así la palabra "look" tanto como sea posible. Podría simplificarse y envolverse dentro de la función aquí para mejorar el rendimiento.
La función anterior también implementa la conversión a minúsculas, pero eso es una muestra. El código para hacerlo ha sido comentado.
Aquí, mira esta función:
function seo_friendly_url($string){
$string = str_replace(array('[\', \']'), '', $string);
$string = preg_replace('/\[.*\]/U', '', $string);
$string = preg_replace('/&(amp;)?#?[a-z0-9]+;/i', '-', $string);
$string = htmlentities($string, ENT_COMPAT, 'utf-8');
$string = preg_replace('/&([a-z])(acute|uml|circ|grave|ring|cedil|slash|tilde|caron|lig|quot|rsquo);/i', '\\1', $string );
$string = preg_replace(array('/[^a-z0-9]/i', '/[-]+/') , '-', $string);
return strtolower(trim($string, '-'));
}