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


Respuestas:


414
string s = "søme string";
s = Regex.Replace(s, @"[^\u0000-\u007F]+", string.Empty);

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.


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

1
En mi humilde opinión Esta respuesta es mejor que la respuesta aceptada porque elimina los caracteres de control.
Dean2690


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.


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

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


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.


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.


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

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.


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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.