Come si possono eliminare caratteri non ASCII da una stringa? (in C #)


227

Come si possono eliminare caratteri non ASCII da una stringa? (in C #)


4
Di seguito , secondo la risposta di Sinelaw , se si desidera sostituire i caratteri non ASCII, vedere invece questa risposta .
Bobson,

Risposte:


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

19
Per quelli che RegEx ha sfidato, ti dispiacerebbe scrivere in inglese il tuo schema RegEx. In altre parole, "il ^ fa questo", ecc ...
Puffo Metro

47
@Metro Puffo il ^ non è l'operatore. Indica alla regex di trovare tutto ciò che non corrisponde, invece di tutto ciò che corrisponde. Il \ u #### - \ u #### dice quali caratteri corrispondono. \ U0000- \ u007F è l'equivalente dei primi 255 caratteri in utf-8 o unicode, che sono sempre i caratteri ASCII. Quindi abbini ogni personaggio non ascii (a causa del non) e sostituisci tutto ciò che corrisponde.
Gordon Tucker,

41
L'intervallo per i caratteri stampabili è 0020-007E, per le persone che cercano un'espressione regolare per sostituire i caratteri non stampabili
Mubashar,

1
@GordonTucker \ u0000- \ u007F è l'equivalente dei primi 127 caratteri in utf-8 o unicode e NON il primo 225. Vedi tabella
full_prog_full

4
@full_prog_full Ecco perché ho risposto a me stesso circa un minuto dopo correggendomi per dire che era 127 e non 255. :)
Gordon Tucker il

125

Ecco una soluzione .NET pura che non utilizza espressioni regolari:

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

Può sembrare ingombrante, ma dovrebbe essere intuitivo. Utilizza la codifica ASCII .NET per convertire una stringa. UTF8 viene utilizzato durante la conversione perché può rappresentare uno qualsiasi dei caratteri originali. Utilizza un EncoderReplacementFallback per convertire qualsiasi carattere non ASCII in una stringa vuota.


5
Perfetto! Sto usando questo per pulire una stringa prima di salvarla in un documento RTF. Davvero apprezzato. Molto più facile da capire rispetto alla versione Regex.
Nathan Prather,

21
Lo trovi davvero più facile da capire? Per me, tutto ciò che non è veramente rilevante (fallback, conversioni in byte ecc.) Sta distogliendo l'attenzione da ciò che accade realmente.
bzlm,

21
È un po 'come dire che i cacciaviti sono troppo confusi, quindi userò solo un martello.
Brandon,

8
@Brandon, in realtà, questa tecnica non fa il lavoro meglio di altre tecniche. Quindi l'analogia sarebbe usare un semplice vecchio cacciavite invece di un elegante iScrewDriver Deluxe 2000. :)
bzlm

10
Un vantaggio è che posso facilmente sostituire ASCII con ISO 8859-1 o un'altra codifica :)
Akira Yamamoto

38

Credo che MonsCamus intendesse:

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

1
IMHO Questa risposta è migliore della risposta accettata perché rimuove i caratteri di controllo.
Dean2690,


11

Ispirato alla soluzione Regular Expression di philcruz , ho realizzato una soluzione LINQ pura

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

Questo è un codice non testato.


1
Per coloro che non l'hanno preso, questa è una soluzione basata su LINQ C # 4.0. :)

7
Invece del metodo ToText () separato, che ne dici di sostituire la riga 3 di PureAscii () con: return new string (source.Select (c => c <min? Nil: c> max? Nil: c) .ToArray ()) ;
agentnega,

O forse ToText come: return (nuova stringa (sorgente)). ToArray () - a seconda di ciò che funziona meglio. È ancora bello avere ToText come metodo di estensione - stile fluente / pipeline. :-)
Bent Rasmussen,

Tale codice sostituisce i caratteri non ASCII con uno spazio. Per eliminarli, cambia Seleziona in Dove:return new string( source.Where( c => c >= min && c <= max ).ToArray() );
Foozinator

@Foozinator Tale codice consente di specificare con quale carattere sostituire i caratteri non ASCII. Di default usa uno spazio, ma se si chiama come .PureASCII (Char.MinValue), sostituirà tutti i caratteri non ASCII con '\ 0' - che comunque non li rimuove esattamente, ma risultati simili.
Ulfius,

5

non c'è bisogno di regex. basta usare la codifica ...

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

5
Questo non funziona. Questo non rimuove i caratteri Unicode, li sostituisce con? carattere.
David,

1
@ David ha ragione. Almeno ho avuto ????nacho??quando ho provato: たまねこnachoなちin mono 3.4
nacho4d

1
È possibile creare un'istanza della propria classe di codifica che invece di sostituire i caratteri li rimuove. Vedere il metodo GetEncoding: msdn.microsoft.com/en-us/library/89856k4b(v=vs.110).aspx
kkara

4

Ho trovato utile il seguente intervallo leggermente modificato per analizzare i blocchi di commenti fuori da un database, questo significa che non dovrete fare i conti con i caratteri tab e escape che provocherebbero il ribaltamento di un campo CSV.

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

Se vuoi evitare altri caratteri speciali o punteggiatura particolare controlla la tabella ASCII


1
Nel caso in cui qualcuno non abbia notato gli altri commenti, i caratteri stampabili sono in realtà @ "[^ \ u0020- \ u007E]". Ecco un link per vedere la tabella se sei curioso: asciitable.com
scradam,

3

Sono venuto qui alla ricerca di una soluzione per caratteri ASCII estesi, ma non sono riuscito a trovarlo. Il più vicino che ho trovato è la soluzione di bzlm . Ma questo funziona solo per il codice ASCII fino a 127 (ovviamente puoi sostituire il tipo di codifica nel suo codice, ma penso che sia stato un po 'complesso da capire. Quindi, condividere questa versione). Ecco una soluzione che funziona con codici ASCII estesi, ovvero fino a 255, ovvero ISO 8859-1

Trova e rimuove caratteri non ascii (maggiore di 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:

Ecco un violino funzionante per il codice

Sostituisci la codifica secondo il requisito, il resto dovrebbe rimanere lo stesso.


2
L'unico che ha funzionato per rimuovere SOLO Ω da questa stringa "Ω c ç ã". Grazie mille!
Rafael Araújo,

2

Questo non è un rendimento ottimale dal punto di vista delle prestazioni, ma un approccio Linq piuttosto diretto:

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

Il rovescio della medaglia è che tutti i personaggi "sopravvissuti" vengono prima messi in una matrice di tipo char[]che viene poi gettata via dopo che il stringcostruttore non lo utilizza più.


1

Ho usato questa espressione regex:

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

16
Questo rimuove anche la punteggiatura, nel caso in cui non è quello che qualcuno vuole.
Drew Noakes,

1

Uso questa espressione regolare per filtrare i caratteri errati in un nome file.

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

Dovrebbero essere tutti i caratteri consentiti per i nomi dei file.


1
No. Vedere Path.GetInvalidPathChars e Path.GetInvalidFileNameChars . Quindi, ci sono decine di migliaia di personaggi validi.
Tom Blodget il

Hai ragione, Tom. In realtà stavo pensando a quelli comuni, ma ho lasciato fuori la parentesi e le parentesi graffe e tutti questi - ^% $ # @! & + =.
user890332
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.