Comment supprimer des caractères non ASCII d'une chaîne? (en C #)


227

Comment supprimer des caractères non ASCII d'une chaîne? (en C #)


4
Selon la réponse de Sinelaw ci - dessous , si vous souhaitez remplacer les caractères non ASCII à la place, consultez plutôt cette réponse .
Bobson

Réponses:


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

19
Pour ceux d'entre nous qui ont défié RegEx, cela vous dérangerait d'écrire en anglais simple votre modèle RegEx. En d'autres termes, "le ^ fait ça", etc ...
Metro Smurf

47
@Metro Smurf the ^ est l'opérateur not. Il dit au regex de trouver tout ce qui ne correspond pas, au lieu de tout ce qui correspond. Le \ u #### - \ u #### indique quels caractères correspondent. \ U0000- \ u007F est l'équivalent des 255 premiers caractères en utf-8 ou unicode, qui sont toujours les caractères ascii. Donc, vous faites correspondre tous les caractères non ascii (à cause du non) et faites un remplacement sur tout ce qui correspond.
Gordon Tucker

41
La plage de caractères imprimables est 0020-007E, pour les personnes recherchant une expression régulière pour remplacer les caractères non imprimables
Mubashar

1
@GordonTucker \ u0000- \ u007F est l'équivilent des 127 premiers caractères en utf-8 ou unicode et PAS les 225 premiers. Voir tableau
full_prog_full

4
@full_prog_full C'est pourquoi je me suis répondu une minute plus tard en me corrigeant pour dire que c'était 127 et non 255. :)
Gordon Tucker

125

Voici une solution .NET pure qui n'utilise pas d'expressions régulières:

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

Cela peut sembler lourd, mais cela devrait être intuitif. Il utilise l'encodage ASCII .NET pour convertir une chaîne. UTF8 est utilisé lors de la conversion car il peut représenter n'importe lequel des caractères d'origine. Il utilise un EncoderReplacementFallback pour convertir tout caractère non ASCII en une chaîne vide.


5
Parfait! J'utilise ceci pour nettoyer une chaîne avant de l'enregistrer dans un document RTF. Très apprécié. Beaucoup plus facile à comprendre que la version Regex.
Nathan Prather

21
Vous trouvez vraiment plus facile à comprendre? Pour moi, tout ce qui n'est pas vraiment pertinent (repli, conversion en octets, etc.) détourne l'attention de ce qui se passe réellement.
bzlm

21
C'est un peu comme dire que les tournevis sont trop confus donc je vais juste utiliser un marteau à la place.
Brandon

8
@Brandon, en fait, cette technique ne fait pas mieux que d'autres techniques. Donc, l'analogie serait d'utiliser un tournevis ordinaire à la place d'un iScrewDriver Deluxe 2000. :)
bzlm

10
Un avantage est que je peux facilement remplacer ASCII par ISO 8859-1 ou un autre encodage :)
Akira Yamamoto

38

Je crois que MonsCamus voulait dire:

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

1
IMHO Cette réponse est meilleure que la réponse acceptée car elle supprime les caractères de contrôle.
Dean2690


11

Inspiré par la solution d'expression régulière de philcruz , j'ai créé une solution LINQ pure

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

Il s'agit d'un code non testé.


1
Pour ceux qui ne l'ont pas compris, il s'agit d'une solution basée sur LINQ C # 4.0. :)

7
Au lieu de la méthode ToText () séparée, que diriez-vous de remplacer la ligne 3 de PureAscii () par: return new string (source.Select (c => c <min? Nil: c> max? Nil: c) .ToArray ()) ;
agentnega

Ou peut-être ToText comme: return (nouvelle chaîne (source)). ToArray () - selon ce qui fonctionne le mieux. C'est toujours agréable d'avoir ToText comme méthode d'extension - style fluide / pipeline. :-)
Bent Rasmussen

Ce code remplace les caractères non ASCII par un espace. Pour les retirer, changez Sélectionner pour Où:return new string( source.Where( c => c >= min && c <= max ).ToArray() );
Foozinator

@Foozinator Ce code vous permet de spécifier avec quel caractère remplacer les caractères non ASCII. Par défaut, il utilise un espace, mais s'il est appelé comme .PureASCII (Char.MinValue), il remplacera tous les non-ASCII par '\ 0' - ce qui ne les supprime toujours pas exactement, mais des résultats similaires.
Ulfius

5

pas besoin de regex. utilisez simplement l'encodage ...

sOutput = System.Text.Encoding.ASCII.GetString(System.Text.Encoding.ASCII.GetBytes(sInput));

5
Cela ne fonctionne pas. Cela ne supprime pas les caractères unicode, il les remplace par le? personnage.
David

1
@David a raison. Au moins, j'ai eu ????nacho??quand j'ai essayé: たまねこnachoなちen mono 3.4
nacho4d

1
Vous pouvez instancier votre propre classe d'encodage qui, au lieu de remplacer les caractères, les supprime. Voir la méthode GetEncoding: msdn.microsoft.com/en-us/library/89856k4b(v=vs.110).aspx
kkara

4

J'ai trouvé la plage légèrement modifiée suivante utile pour analyser les blocs de commentaires d'une base de données, cela signifie que vous n'aurez pas à composer avec des tabulations et des caractères d'échappement qui pourraient perturber un champ CSV.

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

Si vous voulez éviter d'autres caractères spéciaux ou une ponctuation particulière, consultez le tableau ascii


1
Si quelqu'un n'a pas remarqué les autres commentaires, les caractères imprimables sont en fait @ "[^ \ u0020- \ u007E]". Voici un lien pour voir le tableau si vous êtes curieux: asciitable.com
scradam

3

Je suis venu ici à la recherche d'une solution pour les caractères ascii étendus, mais je ne l'ai pas trouvée. Le plus proche que j'ai trouvé est la solution de bzlm . Mais cela ne fonctionne que pour le code ASCII jusqu'à 127 (évidemment, vous pouvez remplacer le type d'encodage dans son code, mais je pense que c'était un peu complexe à comprendre. Par conséquent, partager cette version). Voici une solution qui fonctionne pour les codes ASCII étendus, c'est-à-dire jusqu'à 255, qui est l' ISO 8859-1

Il trouve et supprime les caractères non ascii (supérieurs à 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:

Voici un violon de travail pour le code

Remplacez l'encodage selon l'exigence, le reste doit rester le même.


2
Le seul qui a travaillé pour supprimer UNIQUEMENT le Ω de cette chaîne "Ω c ç ã". Merci beaucoup!
Rafael Araújo

2

Ce n'est pas une performance optimale, mais une approche Linq assez simple:

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

L'inconvénient est que tous les personnages "survivants" sont d'abord placés dans un tableau de type char[]qui est ensuite jeté après que le stringconstructeur ne l'utilise plus.


1

J'ai utilisé cette expression régulière:

    string s = "søme string";
    Regex regex = new Regex(@"[^a-zA-Z0-9\s]", (RegexOptions)0);
    return regex.Replace(s, "");

16
Cela supprime également la ponctuation, juste au cas où ce n'est pas ce que quelqu'un veut.
Drew Noakes

1

J'utilise cette expression régulière pour filtrer les mauvais caractères dans un nom de fichier.

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

Cela devrait être tous les caractères autorisés pour les noms de fichiers.


1
Nan. Voir Path.GetInvalidPathChars et Path.GetInvalidFileNameChars . Il y a donc des dizaines de milliers de caractères valides.
Tom Blodget

Tu as raison, Tom. Je pensais en fait aux plus courants, mais j'ai laissé de côté les parenthèses et les accolades ainsi que tous ces - ^% $ # @! & + =.
user890332
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.