Bagaimana Anda bisa menghapus karakter non-ASCII dari string? (dalam C #)

227

Bagaimana Anda bisa menghapus karakter non-ASCII dari string? (dalam C #)

philcruz
sumber
4
Per jawaban sinelaw di bawah ini , jika Anda ingin mengganti karakter non-ASCII, lihat jawaban ini sebagai gantinya .
Bobson

Jawaban:

414
string s = "søme string";
s = Regex.Replace(s, @"[^\u0000-\u007F]+", string.Empty);
philcruz
sumber
19
Bagi kita yang ditantang RegEx, maukah Anda menuliskan dalam bahasa Inggris polos pola RegEx Anda. Dengan kata lain, "the ^ do this", etc ...
Metro Smurf
47
@Metro Smurf the ^ adalah bukan operator. Ini memberitahu regex untuk menemukan semua yang tidak cocok, bukan semua yang cocok. The \ u #### - \ u #### mengatakan karakter mana yang cocok. \ U0000- \ u007F adalah ekuivalen dari 255 karakter pertama dalam utf-8 atau unicode, yang selalu merupakan karakter ascii. Jadi Anda mencocokkan setiap karakter non ascii (karena tidak) dan melakukan penggantian pada semua yang cocok.
Gordon Tucker
41
Rentang untuk karakter yang dapat dicetak adalah 0020-007E, untuk orang yang mencari ekspresi reguler untuk menggantikan karakter yang tidak dapat dicetak
Mubashar
1
@GordonTucker \ u0000- \ u007F adalah ekuivalen dari 127 karakter pertama dalam utf-8 atau unicode dan BUKAN yang pertama 225. Lihat tabel
full_prog_full
4
@full_prog_full Itulah sebabnya saya menjawab pada diri sendiri sekitar satu menit kemudian mengoreksi diri saya untuk mengatakan itu 127 dan bukan 255. :)
Gordon Tucker
125

Berikut adalah solusi .NET murni yang tidak menggunakan ekspresi reguler:

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

Ini mungkin terlihat rumit, tetapi harus intuitif. Menggunakan pengkodean .NET ASCII untuk mengonversi string. UTF8 digunakan selama konversi karena dapat mewakili karakter asli. Ia menggunakan EncoderReplacementFallback untuk mengubah karakter non-ASCII menjadi string kosong.

bzlm
sumber
5
Sempurna! Saya menggunakan ini untuk membersihkan string sebelum menyimpannya ke dokumen RTF. Sangat dihargai. Jauh lebih mudah dipahami daripada versi Regex.
Nathan Prather
21
Anda benar-benar merasa lebih mudah untuk dipahami? Bagi saya, semua hal yang tidak benar-benar relevan (fallbacks, konversi ke byte, dll) menarik perhatian dari apa yang sebenarnya terjadi.
bzlm
21
Ini seperti mengatakan obeng terlalu membingungkan, jadi saya hanya akan menggunakan palu.
Brandon
8
@Brandon, sebenarnya, teknik ini tidak melakukan pekerjaan lebih baik daripada teknik lainnya. Jadi analoginya akan menggunakan obeng olde biasa bukan iScrewDriver Deluxe 2000 mewah :).
bzlm
10
Satu keuntungan adalah saya dapat dengan mudah mengganti ASCII dengan ISO 8859-1 atau penyandian lainnya :)
Akira Yamamoto
38

Saya percaya MonsCamus berarti:

parsememo = Regex.Replace(parsememo, @"[^\u0020-\u007E]", string.Empty);
Josh
sumber
1
IMHO Jawaban ini lebih baik daripada jawaban yang diterima karena menghapus karakter kontrol.
Dean2690
15

Jika Anda tidak ingin menghapus, tetapi untuk benar-benar mengubah aksen latin ke karakter non-aksen, lihat pertanyaan ini: Bagaimana cara menerjemahkan 8bit karakter menjadi 7bit karakter? (yaitu Ü to U)

sinelaw
sumber
Saya bahkan tidak menyadari ini mungkin, tetapi itu solusi yang jauh lebih baik bagi saya. Saya akan menambahkan tautan ini ke komentar pada pertanyaan untuk memudahkan orang lain menemukannya. Terima kasih!
Bobson
11

Terinspirasi oleh solusi Regular Expression dari philcruz , saya telah membuat solusi LINQ murni

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

Ini adalah kode yang belum diuji.

Bent Rasmussen
sumber
1
Bagi mereka yang tidak menangkapnya, ini adalah solusi berbasis C # 4.0 LINQ. :)
7
Alih-alih metode ToText () yang terpisah, bagaimana dengan mengganti baris 3 dari PureAscii () dengan: mengembalikan string baru (source.Pilih (c => c <min? Nil: c> max? Nil: c) .ToArray ()) ;
agentnega
Atau mungkin ToText sebagai: return (string baru (sumber)). ToArray () - tergantung pada apa yang berkinerja terbaik. Masih bagus untuk memiliki ToText sebagai metode ekstensi - gaya fasih / pipa. :-)
Bent Rasmussen
Kode itu menggantikan karakter non-ASCII dengan spasi. Untuk menghapusnya, ubah Pilih ke Tempat:return new string( source.Where( c => c >= min && c <= max ).ToArray() );
Foozinator
@Foozinator Kode itu memungkinkan Anda menentukan karakter mana yang akan menggantikan karakter non-ASCII. Secara default ia menggunakan spasi, tetapi jika disebut seperti. PureASCII (Char.MinValue), ia akan mengganti semua non-ASCII dengan '\ 0' - yang masih belum benar-benar menghapusnya, tetapi hasilnya serupa.
Ulfius
5

tidak perlu regex. cukup gunakan pengodean ...

sOutput = System.Text.Encoding.ASCII.GetString(System.Text.Encoding.ASCII.GetBytes(sInput));
rjp
sumber
5
Ini tidak bekerja. Ini tidak menghapus karakter unicode, itu menggantikannya dengan? karakter.
David
1
@ David benar. Setidaknya saya dapatkan ????nacho??ketika saya mencoba: たまねこnachoなちdi mono 3.4
nacho4d
1
Anda dapat membuat instance kelas Pengkodean Anda sendiri alih-alih mengganti karakter yang dihapusnya. Lihat metode GetEncoding: msdn.microsoft.com/en-us/library/89856k4b(v=vs.110).aspx
kkara
4

Saya menemukan kisaran berikut yang sedikit diubah berguna untuk mem-parsing blok komentar dari database, ini berarti Anda tidak perlu bersaing dengan tab dan melarikan diri karakter yang akan menyebabkan bidang CSV menjadi marah.

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

Jika Anda ingin menghindari karakter khusus atau tanda baca tertentu, periksa tabel ascii

MonsCamus
sumber
1
Jika ada yang tidak memperhatikan komentar lain, karakter yang dapat dicetak sebenarnya @ "[^ \ u0020- \ u007E]". Berikut ini tautan untuk melihat tabel jika Anda penasaran: asciitable.com
scradam
3

Saya datang ke sini mencari solusi untuk karakter ascii yang diperluas, tetapi tidak dapat menemukannya. Yang paling dekat yang saya temukan adalah solusi bzlm . Tapi itu hanya berfungsi untuk ASCII Code hingga 127 (jelas Anda dapat mengganti jenis pengkodean dalam kodenya, tetapi saya pikir itu agak rumit untuk dipahami. Oleh karena itu, bagikan versi ini). Berikut adalah solusi yang berfungsi untuk kode ASCII yang diperluas yaitu hingga 255 yang merupakan ISO 8859-1

Ia menemukan dan menghapus karakter non-ascii (lebih dari 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:

Ini biola yang berfungsi untuk kodenya

Ganti pengkodean sesuai kebutuhan, sisanya harus tetap sama.

Proton polinomial
sumber
2
Satu-satunya yang bekerja untuk menghapus HANYA Ω dari string ini "Ω c ç ã". Terima kasih banyak!
Rafael Araújo
2

Ini bukan kinerja-bijaksana yang optimal, tetapi pendekatan Linq cukup lurus ke depan:

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

Kelemahannya adalah bahwa semua karakter yang "bertahan" pertama kali dimasukkan ke dalam array tipe char[]yang kemudian dibuang setelah stringkonstruktor tidak lagi menggunakannya.

Jeppe Stig Nielsen
sumber
1

Saya menggunakan ungkapan regex ini:

    string s = "søme string";
    Regex regex = new Regex(@"[^a-zA-Z0-9\s]", (RegexOptions)0);
    return regex.Replace(s, "");
Pengecut anonim
sumber
16
Ini menghilangkan tanda baca juga, kalau-kalau itu bukan yang diinginkan seseorang.
Drew Noakes
1

Saya menggunakan persamaan reguler ini untuk memfilter karakter buruk dalam nama file.

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

Itu harus semua karakter yang diizinkan untuk nama file.

pengguna890332
sumber
1
Nggak. Lihat Path.GetInvalidPathChars dan Path.GetInvalidFileNameChars . Jadi, ada puluhan ribu karakter yang valid.
Tom Blodget
Anda benar, Tom. Saya benar-benar memikirkan yang umum, tetapi saya meninggalkan kurung dan kurung kurawal serta semua ini - ^% $ # @! & + =.
user890332