¿Cómo elimino todos los caracteres no alfanuméricos de una cadena, excepto el guión?

684

¿Cómo elimino todos los caracteres no alfanuméricos de una cadena, excepto los guiones y los espacios?

968

Reemplazar [^a-zA-Z0-9 -]con una cadena vacía.

Regex rgx = new Regex("[^a-zA-Z0-9 -]");
str = rgx.Replace(str, "");
18
  • 90
    Vale la pena mencionar que -debe estar al final de la clase de personaje, o escapar con una barra invertida, para evitar que se use para un rango. 9/07/10 a las 9:18
  • 6
    @Dan establece la bandera global en su expresión regular; sin eso, simplemente reemplaza la primera coincidencia. Un google rápido debería decirle cómo establecer una bandera global en la expresión regular ASP clásica. De lo contrario, busque una replaceAllfunción en lugar de replace. 22 de septiembre de 2010 a las 3:49
  • 23
    Aquí hay una versión compilada de expresiones regulares: la return Regex.Replace(str, "[^a-zA-Z0-9_.]+", "", RegexOptions.Compiled); misma pregunta básica 30/09/11 a las 16:35
  • 15
    @MGOwen porque cada vez que usas "" estás creando un nuevo objeto debido a que las cadenas son inmutables. Cuando usa string.empty, está reutilizando la instancia única requerida para representar una cadena vacía, lo que es más rápido y más eficiente. 18/06/12 a las 11:09
  • 17
    @BrianScott Sé que esto es antiguo, pero lo encontré en una búsqueda, así que creo que es relevante. En realidad, esto depende de la versión de .NET con la que se esté ejecutando. > 2.0 utiliza ""y string.Emptyexactamente lo mismo. stackoverflow.com/questions/151472/…
    Jared
    23/10/12 a las 21:08
373

Podría haber usado RegEx, pueden proporcionar una solución elegante pero pueden causar problemas de rendimiento. Aquí hay una solución

char[] arr = str.ToCharArray();

arr = Array.FindAll<char>(arr, (c => (char.IsLetterOrDigit(c) 
                                  || char.IsWhiteSpace(c) 
                                  || c == '-')));
str = new string(arr);

Al usar el marco compacto (que no tiene FindAll)

Reemplazar FindAll con 1

char[] arr = str.Where(c => (char.IsLetterOrDigit(c) || 
                             char.IsWhiteSpace(c) || 
                             c == '-')).ToArray(); 

str = new string(arr);

1 comentario de ShawnFeatherly

4
  • 44
    en mis pruebas, esta técnica fue mucho más rápida. para ser precisos, fue un poco menos de 3 veces más rápido que la técnica Regex Replace.
    Dan
    11/08/11 a las 15:49
  • 13
    El marco compacto no tiene FindAll, puede reemplazar FindAll con char[] arr = str.Where(c => (char.IsLetterOrDigit(c) || char.IsWhiteSpace(c) || c == '-')).ToArray(); 25/01/2013 a las 22:14
  • 2
    ¿Alguien ha probado esto? Eso no funcionó en absoluto. --pero esto me sirvió: string str2 = new string (str.Where (c => (char.IsLetterOrDigit (c))). ToArray ()); 16/12/2016 a las 21:31
  • Como una sola línea str = string.Concat(str.Where(c => Char.IsLetterOrDigit(c) || Char.IsWhiteSpace(c)))
    VDWWD
    11 de mayo a las 15:33
63

Puedes probar:

string s1 = Regex.Replace(s, "[^A-Za-z0-9 -]", "");

¿Dónde sestá tu cuerda?

3
  • 1
    OP pidió guión, no subrayado
    Sean B
    22/04/2017 a las 21:02
  • Esto no funciona ya que da un error de "símbolo no encontrado", incluso después de importar java.util.regex. * 20/11/20 a las 21:31
  • 2
    @DavidBandel es C #
    m47730
    22 de enero a las 15:17
45

Usando System.Linq

string withOutSpecialCharacters = new string(stringWithSpecialCharacters.Where(c =>char.IsLetterOrDigit(c) || char.IsWhiteSpace(c) || c == '-').ToArray());
4
  • @Michael Es similar, pero al menos se trata de una línea, en lugar de 3 líneas. Yo diría que eso es suficiente para que sea una respuesta diferente.
    Dymas
    25/04/19 a las 17:37
  • 1
    @Dymas Ahora estoy de acuerdo en que es aceptable, pero no porque el espacio en blanco sea diferente. Aparentemente, la parte que es funcionalmente equivalente (solo los nombres de var difieren) se editó después de que se escribió esta respuesta.
    Michael
    25/04/19 a las 18:26
  • 1
    @ZainAli, si haces una edición trivial y me haces ping, revertiré mi voto negativo. Pido disculpas por cualquier insinuación de plagio.
    Michael
    25/04/19 a las 18:28
  • Me gusta este, definitivamente un fragmento útil, ¡gracias! 26 de enero a las 12:58
25

La expresión regular es [^\w\s\-]*:

\ses mejor usar en lugar de espacio ( ), porque puede haber una pestaña en el texto.

9
  • 1
    a menos que desee eliminar pestañas. 9 de julio de 2010 a las 6:57
  • ... y nuevas líneas, y todos los demás caracteres considerados "espacios en blanco". 9/07/10 a las 9:17
  • 7
    Esta solución es muy superior a las soluciones anteriores, ya que también admite caracteres internacionales (no ingleses). <! - language: c # -> string s = "Mötley Crue 日本人: の 氏 名 y Kanji 愛 e Hiragana あ い"; cadena r = Regex.Replace (s, "[^ \\ w \\ s -] *", ""); Lo anterior produce r con: Mötley Crue 日本人 の 氏 名 y Kanji 愛 e Hiragana あ い 3 feb 2014 a las 12:12
  • 2
    Use @ para escapar de \ conversión en la cadena: @ "[^ \ w \ s -] *" 28 feb 2014 a las 11:45
  • 1
    eso, uhhh ... ¿no quita los guiones bajos? que se considera un carácter de "palabra" por la implementación de expresiones regulares a lo largo de la creación, pero no es alfanumérico, guión o espacio ... (?) 16/11/15 a las 14:22
20

Según la respuesta a esta pregunta, creé una clase estática y las agregué. Pensé que podría ser útil para algunas personas.

public static class RegexConvert
{
    public static string ToAlphaNumericOnly(this string input)
    {
        Regex rgx = new Regex("[^a-zA-Z0-9]");
        return rgx.Replace(input, "");
    }

    public static string ToAlphaOnly(this string input)
    {
        Regex rgx = new Regex("[^a-zA-Z]");
        return rgx.Replace(input, "");
    }

    public static string ToNumericOnly(this string input)
    {
        Regex rgx = new Regex("[^0-9]");
        return rgx.Replace(input, "");
    }
}

Entonces los métodos se pueden usar como:

string example = "[email protected]#$";
string alphanumeric = example.ToAlphaNumericOnly();
string alpha = example.ToAlphaOnly();
string numeric = example.ToNumericOnly();
2
  • 2
    Para el ejemplo que proporciona, también sería útil si proporciona los resultados de cada uno de los métodos. 25/03/18 a las 18:56
  • Esta solución depende de la cultura.
    ndogac
    27/09/20 a las 18:04
11

¿Quieres algo rápido?

public static class StringExtensions 
{
    public static string ToAlphaNumeric(this string self, params char[] allowedCharacters)
    {
        return new string(Array.FindAll(self.ToCharArray(), c => char.IsLetterOrDigit(c) || allowedCharacters.Contains(c)));
    }
}

Esto le permitirá especificar qué caracteres desea permitir también.

2
  • En mi humilde opinión, la mejor solución aquí.
    suchoss
    25 sep.20 a las 18:48
  • Parece limpio, pero es un poco difícil especificar cómo agregar espacios en blanco. Habría agregado otra sobrecarga que también permite espacios en blanco, ya que este método funciona bien en palabras, pero no en oraciones u otros espacios en blanco, como nuevas líneas o pestañas. +1 de todos modos, buena solución. public static string ToAlphaNumericWithWhitespace (esta cadena self, params char [] allowedCharacters) {return new string (Array.FindAll (self.ToCharArray (), c => char.IsLetterOrDigit (c) || ​​char.IsWhiteSpace (c) || ​​allowedCharacters .Contiene (c))); } 26 de agosto a las 12:15
5

Aquí hay una solución rápida amigable para la asignación de montón sin expresiones regulares que era lo que estaba buscando.

Edición insegura.

public static unsafe void ToAlphaNumeric(ref string input)
{
    fixed (char* p = input)
    {
        int offset = 0;
        for (int i = 0; i < input.Length; i++)
        {
            if (char.IsLetterOrDigit(p[i]))
            {
                p[offset] = input[i];
                offset++;
            }
        }
        ((int*)p)[-1] = offset; // Changes the length of the string
        p[offset] = '\0';
    }
}

Y para aquellos que no quieren usar inseguros o no confían en el truco de la longitud de la cuerda.

public static string ToAlphaNumeric(string input)
{
    int j = 0;
    char[] newCharArr = new char[input.Length];

    for (int i = 0; i < input.Length; i++)
    {
        if (char.IsLetterOrDigit(input[i]))
        {
            newCharArr[j] = input[i];
            j++;
        }
    }

    Array.Resize(ref newCharArr, j);

    return new string(newCharArr);
}
1
  • No debe alterar el contenido de la cadena debido a la agrupación de cadenas.
    ndogac
    27/09/20 a las 18:13
4

Hice una solución diferente, eliminando los caracteres de Control , que era mi problema original.

Es mejor que poner en una lista todos los caracteres "especiales pero buenos"

char[] arr = str.Where(c => !char.IsControl(c)).ToArray();    
str = new string(arr);

¡Es más simple, así que creo que es mejor!

3

Aquí hay un método de extensión que usa la respuesta @ata como inspiración.

"hello-world123, 456".MakeAlphaNumeric(new char[]{'-'});// yields "hello-world123456"

o si necesita caracteres adicionales además del guión ...

"hello-world123, 456!?".MakeAlphaNumeric(new char[]{'-','!'});// yields "hello-world123456!"


public static class StringExtensions
{   
    public static string MakeAlphaNumeric(this string input, params char[] exceptions)
    {
        var charArray = input.ToCharArray();
        var alphaNumeric = Array.FindAll<char>(charArray, (c => char.IsLetterOrDigit(c)|| exceptions?.Contains(c) == true));
        return new string(alphaNumeric);
    }
}
1

Si está trabajando en JS, aquí hay una versión muy concisa

myString = myString.replace(/[^A-Za-z0-9 -]/g, "");
1
  • 1
    Creo que OP podría haber preguntado sobre C #, no sobre JS. 5/10/20 a las 10:06
0

Utilizo una variación de una de las respuestas aquí. Quiero reemplazar los espacios con "-" para que sea compatible con SEO y también en minúsculas. Tampoco hace referencia a system.web desde mi capa de servicios.

private string MakeUrlString(string input)
{
    var array = input.ToCharArray();

    array = Array.FindAll<char>(array, c => char.IsLetterOrDigit(c) || char.IsWhiteSpace(c) || c == '-');

    var newString = new string(array).Replace(" ", "-").ToLower();
    return newString;
}
-1

Hay una forma mucho más fácil con Regex.

private string FixString(string str)
{
    return string.IsNullOrEmpty(str) ? str : Regex.Replace(str, "[\\D]", "");
}
1
  • 2
    solo reemplaza caracteres no numéricos 28 de agosto de 2017 a las 12:36