Reemplace todos los caracteres que no sean letras ni números con un guión [duplicado]

Resuelto user115422 asked hace 54 años • 3 respuestas

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)...

user115422 avatar Jan 01 '70 08:01 user115422
Aceptado

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.
}
Terry Harvey avatar Jan 01 '2013 21:01 Terry Harvey

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. $dictPor 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 cleanStringimplementació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.

LSerni avatar Jan 01 '2013 21:01 LSerni

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, '-'));
}
Jeffrey avatar Jan 01 '2013 21:01 Jeffrey