¿Cómo puede quitar caracteres no ASCII de una cadena? (C ª#)

227

¿Cómo puede quitar caracteres no ASCII de una cadena? (C ª#)

philcruz
fuente
44
Por la respuesta de sinelaw a continuación , si por el contrario quiere reemplazar caracteres no ASCII, ver esta respuesta en su lugar .
Bobson

Respuestas:

414
string s = "søme string";
s = Regex.Replace(s, @"[^\u0000-\u007F]+", string.Empty);
philcruz
fuente
19
Para aquellos de nosotros que RegEx había desafiado, ¿les importaría escribir en inglés su patrón RegEx? En otras palabras, "the ^ does this", etc ...
Metro Smurf
47
@Metro Smurf the ^ no es el operador. Le dice a la expresión regular que busque todo lo que no coincide, en lugar de todo lo que sí coincide. El \ u #### - \ u #### dice qué caracteres coinciden. \ U0000- \ u007F es el equivalente de los primeros 255 caracteres en utf-8 o unicode, que siempre son los caracteres ascii. Entonces, coincide con todos los caracteres no ascii (debido a que no) y reemplaza todo lo que coincide.
Gordon Tucker
41
El rango para caracteres imprimibles es 0020-007E, para personas que buscan expresiones regulares para reemplazar caracteres no imprimibles
Mubashar
1
@GordonTucker \ u0000- \ u007F es el equivalente de los primeros 127 caracteres en utf-8 o unicode y NO los primeros 225. Ver tabla
full_prog_full
44
@full_prog_full Es por eso que me respondí a mí mismo un minuto después, corrigiéndome para decir que era 127 y no 255. :)
Gordon Tucker
125

Aquí hay una solución .NET pura que no usa expresiones regulares:

string inputString = "Räksmörgås";
string asAscii = Encoding.ASCII.GetString(
    Encoding.Convert(
        Encoding.UTF8,
        Encoding.GetEncoding(
            Encoding.ASCII.EncodingName,
            new EncoderReplacementFallback(string.Empty),
            new DecoderExceptionFallback()
            ),
        Encoding.UTF8.GetBytes(inputString)
    )
);

Puede parecer engorroso, pero debe ser intuitivo. Utiliza la codificación .NET ASCII para convertir una cadena. UTF8 se usa durante la conversión porque puede representar cualquiera de los caracteres originales. Utiliza un EncoderReplacementFallback para convertir cualquier carácter que no sea ASCII en una cadena vacía.

bzlm
fuente
55
¡Perfecto! Estoy usando esto para limpiar una cadena antes de guardarla en un documento RTF. Muy apreciado. Mucho más fácil de entender que la versión Regex.
Nathan Prather
21
¿Realmente te resulta más fácil de entender? Para mí, todo lo que no es realmente relevante (retrocesos, conversiones a bytes, etc.) está alejando la atención de lo que realmente sucede.
bzlm
21
Es algo así como decir que los destornilladores son demasiado confusos, así que solo usaré un martillo.
Brandon
8
@Brandon, en realidad, esta técnica no hace el trabajo mejor que otras técnicas. Entonces, la analogía sería usar un destornillador viejo en lugar de un elegante iScrewDriver Deluxe 2000. :)
bzlm
10
Una ventaja es que puedo reemplazar fácilmente ASCII con ISO 8859-1 u otra codificación :)
Akira Yamamoto
38

Creo que MonsCamus quería decir:

parsememo = Regex.Replace(parsememo, @"[^\u0020-\u007E]", string.Empty);
Josh
fuente
1
En mi humilde opinión Esta respuesta es mejor que la respuesta aceptada porque elimina los caracteres de control.
Dean2690
15

Si no desea eliminar, sino convertir los caracteres latinos con acento en caracteres sin acento, eche un vistazo a esta pregunta: ¿Cómo traduzco caracteres de 8 bits en caracteres de 7 bits? (es decir, de Ü a U)

sinelaw
fuente
Ni siquiera me di cuenta de que esto era posible, pero es una solución mucho mejor para mí. Voy a agregar este enlace a un comentario sobre la pregunta para que sea más fácil de encontrar para otras personas. ¡Gracias!
Bobson
11

Inspirado por la solución de expresión regular de philcruz , he creado una solución pura de LINQ

public static string PureAscii(this string source, char nil = ' ')
{
    var min = '\u0000';
    var max = '\u007F';
    return source.Select(c => c < min ? nil : c > max ? nil : c).ToText();
}

public static string ToText(this IEnumerable<char> source)
{
    var buffer = new StringBuilder();
    foreach (var c in source)
        buffer.Append(c);
    return buffer.ToString();
}

Este es un código no probado.

Bent Rasmussen
fuente
1
Para aquellos que no lo entendieron, esta es una solución basada en LINQ C # 4.0. :)
77
En lugar del método separado ToText (), ¿qué tal reemplazar la línea 3 de PureAscii () con: return new string (source.Select (c => c <min? Nil: c> max? Nil: c) .ToArray ()) ;
agentnega
O tal vez ToText como: return (nueva cadena (fuente)). ToArray () - dependiendo de lo que funcione mejor. Todavía es bueno tener ToText como método de extensión: estilo fluido / de canalización. :-)
Bent Rasmussen
Ese código reemplaza los caracteres no ASCII con un espacio. Para eliminarlos, cambie Seleccionar a Dónde:return new string( source.Where( c => c >= min && c <= max ).ToArray() );
Foozinator
@Foozinator Ese código le permite especificar con qué carácter reemplazar los caracteres no ASCII. De manera predeterminada, utiliza un espacio, pero si se llama como .PureASCII (Char.MinValue), reemplazará todos los que no sean ASCII con '\ 0', lo que aún no los elimina exactamente, pero tiene resultados similares.
Ulfius
5

No hay necesidad de expresiones regulares. solo usa la codificación ...

sOutput = System.Text.Encoding.ASCII.GetString(System.Text.Encoding.ASCII.GetBytes(sInput));
rjp
fuente
55
Esto no funciona. Esto no elimina los caracteres unicode, los reemplaza con el? personaje.
David
1
@David tiene razón. Al menos lo conseguí ????nacho??cuando lo intenté: たまねこnachoなちen mono 3.4
nacho4d
1
Puede crear una instancia de su propia clase de codificación que, en lugar de reemplazar los caracteres, los elimine. Consulte el método GetEncoding: msdn.microsoft.com/en-us/library/89856k4b(v=vs.110).aspx
kkara
4

Encontré que el siguiente rango ligeramente alterado es útil para analizar bloques de comentarios de una base de datos, esto significa que no tendrá que lidiar con tabuladores y caracteres de escape que causarían que un campo CSV se altere.

parsememo = Regex.Replace(parsememo, @"[^\u001F-\u007F]", string.Empty);

Si desea evitar otros caracteres especiales o signos de puntuación particulares, consulte la tabla ASCII

MonsCamus
fuente
1
En caso de que alguien no haya notado los otros comentarios, los caracteres imprimibles son en realidad @ "[^ \ u0020- \ u007E]". Aquí tiene un enlace para ver la tabla si tiene curiosidad: asciitable.com
scradam
3

Vine aquí buscando una solución para caracteres ascii extendidos, pero no pude encontrarla. Lo más cercano que encontré es la solución de bzlm . Pero eso funciona solo para el código ASCII hasta 127 (obviamente, puede reemplazar el tipo de codificación en su código, pero creo que fue un poco complejo de entender. Por lo tanto, compartir esta versión). Aquí hay una solución que funciona para códigos ASCII extendidos, es decir, hasta 255, que es la ISO 8859-1

Encuentra y elimina caracteres no ascii (mayores de 255)

Dim str1 as String= "â, ??î or ôu🕧� n☁i✑💴++$-💯♓!🇪🚑🌚‼⁉4⃣od;/⏬'®;😁☕😁:☝)😁😁///😍1!@#"

Dim extendedAscii As Encoding = Encoding.GetEncoding("ISO-8859-1", 
                                                New EncoderReplacementFallback(String.empty),
                                                New DecoderReplacementFallback())

Dim extendedAsciiBytes() As Byte = extendedAscii.GetBytes(str1)

Dim str2 As String = extendedAscii.GetString(extendedAsciiBytes)

console.WriteLine(str2)
'Output : â, ??î or ôu ni++$-!‼⁉4od;/';:)///1!@#$%^yz:

Aquí está un violín que funciona para el código

Reemplace la codificación según el requisito, el resto debe permanecer igual.

Protón polinomial
fuente
2
El único que funcionó para eliminar SOLO el Ω de esta cadena "Ω c ç ã". ¡Muchas gracias!
Rafael Araújo
2

Este no es un rendimiento óptimo en cuanto a rendimiento, sino un enfoque bastante directo de Linq:

string strippedString = new string(
    yourString.Where(c => c <= sbyte.MaxValue).ToArray()
    );

La desventaja es que todos los caracteres "supervivientes" se colocan primero en una matriz de tipo char[]que luego se desecha después de que el stringconstructor ya no lo usa.

Jeppe Stig Nielsen
fuente
1

Usé esta expresión regular:

    string s = "søme string";
    Regex regex = new Regex(@"[^a-zA-Z0-9\s]", (RegexOptions)0);
    return regex.Replace(s, "");
Cobarde anónimo
fuente
16
Esto también elimina la puntuación, en caso de que eso no sea lo que alguien quiere.
Drew Noakes
1

Utilizo esta expresión regular para filtrar los caracteres incorrectos en un nombre de archivo.

Regex.Replace(directory, "[^a-zA-Z0-9\\:_\- ]", "")

Deben ser todos los caracteres permitidos para los nombres de archivo.

usuario890332
fuente
1
No Ver Path.GetInvalidPathChars y Path.GetInvalidFileNameChars . Entonces, hay decenas de miles de caracteres válidos.
Tom Blodget
Tienes razón, Tom. Realmente estaba pensando en los comunes, pero omití los paréntesis y las llaves, así como todos estos - ^% $ # @! & + =.
user890332