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

606

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

Lucas101
fuente

Respuestas:

870

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

Regex rgx = new Regex("[^a-zA-Z0-9 -]");
str = rgx.Replace(str, "");
Amarghosh
fuente
79
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.
Peter Boughton
66
@Dan establece la bandera global en su expresión regular; sin eso, solo reemplaza la primera coincidencia. Un google rápido debería decirle cómo configurar la marca global en la expresión regular ASP clásica. De lo contrario, busque una replaceAllfunción en lugar de replace.
Amarghosh
20
Aquí hay una versión compilada de expresiones regulares: la return Regex.Replace(str, "[^a-zA-Z0-9_.]+", "", RegexOptions.Compiled); misma pregunta básica
Paige Watson, el
13
@MGOwen porque cada vez que usa "" está 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 que es más rápida y más eficiente.
Brian Scott
17
@BrianScott Sé que esto es viejo, pero se encontró en una búsqueda, así que creo que esto es relevante. Esto realmente depende de la versión de .NET con la que se está ejecutando. > 2.0 usos ""y string.Emptyexactamente lo mismo. stackoverflow.com/questions/151472/…
Jared
348

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

Cuando se usa el marco compacto (que no tiene FindAll)

Reemplace FindAll con 1

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

str = new string(arr);

1 comentario por ShawnFeatherly

ata
fuente
41
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
12
El marco compacto no tiene FindAll, puede reemplazar FindAll conchar[] arr = str.Where(c => (char.IsLetterOrDigit(c) || char.IsWhiteSpace(c) || c == '-')).ToArray();
ShawnFeatherly
2
¿Alguien ha probado esto? Eso no funcionó en absoluto. --pero esto hizo para mí: cadena str2 = cadena nueva (str.Where (c => (char.IsLetterOrDigit (c))). ToArray ());
KevinDeus
48

Puedes probar:

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

¿Dónde sestá tu cuerda?

josephj1989
fuente
1
OP pidió guión, no subrayado
Sean B
39

Usando System.Linq

string withOutSpecialCharacters = new string(stringWithSpecialCharacters.Where(c =>char.IsLetterOrDigit(c) || char.IsWhiteSpace(c) || c == '-').ToArray());
Zain Ali
fuente
@ Michael Es similar, pero al menos este es un trazador de líneas, en lugar de 3 líneas. Yo diría que es suficiente para que sea una respuesta diferente.
Dymas
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 difieren los nombres var) se editó después de escribir esta respuesta.
Michael - ¿Dónde está Clay Shirky?
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 - ¿Dónde está Clay Shirky?
22

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

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

Cierto suave
fuente
1
a menos que quieras eliminar pestañas.
Matt Ellen el
... y líneas nuevas, y todos los demás caracteres considerados "espacios en blanco".
Peter Boughton
66
Esta solución es muy superior a las soluciones anteriores, ya que también admite caracteres internacionales (que no están en inglés). <! - idioma: c # -> string s = "Mötley Crue 日本人: の 氏 名 y Kanji 愛 e Hiragana あ い"; string r = Regex.Replace (s, "[^ \\ w \\ s -] *", ""); Lo anterior produce r con: Mötley Crue 日本人 の 氏 名 y Kanji 愛 e Hiragana あ い
danglund
1
Use @ para escapar \ conversión en cadena: @ "[^ \ w \ s -] *"
Jakub Pawlinski
1
uhhh ... no elimina los guiones bajos? eso se considera un carácter de "palabra" por la implementación de expresiones regulares en la creación, pero no es alfanumérico, guión o espacio ... (?)
Code Jockey
14

Basado en 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 = "asdf1234!@#$";
string alphanumeric = example.ToAlphaNumericOnly();
string alpha = example.ToAlphaOnly();
string numeric = example.ToNumericOnly();
Ppp
fuente
2
Para el ejemplo que proporcione, también sería útil si proporciona los resultados de cada uno de los métodos.
c-chavez
7

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

Zachare Sylvestre
fuente
5

Aquí hay una solución rápida amigable de asignación de almacenamiento no regex 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 inseguro o no confían en el truco de longitud de cadena.

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);
}
BjarkeCK
fuente
4

He hecho 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!

Pinello
fuente
2

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

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

o si necesita caracteres adicionales que no sean guiones ...

"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);
    }
}
Aaron Hudon
fuente
1

Utilizo una variación de una de las respuestas aquí. Quiero reemplazar espacios con "-" para que sea amigable con SEO y también en minúsculas. Tampoco referencia system.web de 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;
}
Philip Johnson
fuente
0

Aquí hay una versión muy concisa

myString = myString.replace(/[^A-Za-z0-9 -]/g, "");
GeekyMonkey
fuente
-1

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

private string FixString(string str)
{
    return string.IsNullOrEmpty(str) ? str : Regex.Replace(str, "[\\D]", "");
}
Desarrollo Syv
fuente
1
solo reemplaza caracteres no numéricos
frostymarvelous