ASCII olmayan karakterleri bir dizeden nasıl ayırabilirsiniz? (C # ile)


227

ASCII olmayan karakterleri bir dizeden nasıl ayırabilirsiniz? (C # ile)


4
Aşağıdaki sinelaw cevabı başına , eğer ASCII olmayan karakterleri değiştirmek istiyorsanız , bunun yerine bu cevaba bakınız .
Bobson

Yanıtlar:


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

19
RegEx'e meydan okuyanlarımız için, RegEx deseninizi düz İngilizce olarak yazabilir misiniz? Başka bir deyişle, "the ^ bunu yapar", vb ...
Metro Şirin,

47
@Metro Smurf, operatör değil. Normal ifadeye, eşleşen her şey yerine eşleşmeyen her şeyi bulmasını söyler. \ U #### - \ u #### hangi karakterlerin eşleştiğini söyler. \ U0000- \ u007F utf-8 veya unicode'daki her zaman ascii karakterleri olan ilk 255 karakterin eşdeğeridir. Böylece her ascii olmayan karakteri eşleştiriyorsunuz (çünkü değil) ve eşleşen her şeyin yerine geçiyorsunuz.
Gordon Tucker

42
Yazdırılamayan karakterlerin aralığı 0020-007E, yazdırılamayan karakterlerin yerine normal ifade arayan insanlar için
Mubashar

1
@GordonTucker \ u0000- \ u007F utf-8 veya unicode'daki ilk 127 karakterin eşdeğeridir ve ilk 225 DEĞİLDİR. Bkz. Tablo
full_prog_full

4
@full_prog_full Bu yüzden bir dakika kadar sonra kendimi düzelterim ve 255 değil 127 olduğunu söylemek için kendimi düzelttim. :)
Gordon Tucker

125

Normal ifadeler kullanmayan saf bir .NET çözümü:

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

Bu hantal görünebilir, ancak sezgisel olmalıdır. Bir dizeyi dönüştürmek için .NET ASCII kodlamasını kullanır. Dönüştürme sırasında UTF8 kullanılır, çünkü orijinal karakterlerden herhangi birini temsil edebilir. ASCII olmayan karakterleri boş bir dizeye dönüştürmek için bir EncoderReplacementFallback kullanır.


5
Mükemmel! Bir RTF belgesine kaydetmeden önce bir dizeyi temizlemek için kullanıyorum. Çok müteşekkirim. Anlamak Regex versiyonundan çok daha kolay.
Nathan Prather

21
Anlamak gerçekten daha kolay mı? Bana göre, gerçekten alakalı olmayan tüm şeyler (yedekler, baytlara dönüştürmeler vb.) Dikkati gerçekte olanlardan uzaklaştırıyor.
bzlm

21
Bu tornavidaların çok kafa karıştırıcı olduğunu söylemek gibi bir çekiç kullanacağım.
Brandon

8
@Brandon, aslında, bu teknik işi diğer tekniklerden daha iyi yapmaz. Bu yüzden benzetme, süslü bir iScrewDriver Deluxe 2000 yerine düz olde tornavida kullanıyor olurdu. :)
bzlm

10
Bir avantajı, ASCII'yi ISO 8859-1 veya başka bir kodlama ile kolayca değiştirebilmem :)
Akira Yamamoto

38

MonsCamus'un kastettiğine inanıyorum:

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

1
IMHO Bu cevap kabul edilen cevaptan daha iyidir çünkü kontrol karakterlerini çıkarır.
Dean2690


11

Philcruz'un Düzenli İfade çözümünden esinlenerek saf bir LINQ çözümü yaptım

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

Bu test edilmemiş kod.


1
Yakalamayanlar için bu C # 4.0 LINQ tabanlı bir çözümdür. :)

7
Ayrı ToText () yöntemi yerine, PureAscii () 'nin 3. satırını: ile değiştir: new string (source.Select (c => c <min? Nil: c> max? Nil: c) .ToArray ()) ;
agentnega

Ya da belki ToText as: return (yeni dize (kaynak)). ToArray () - en iyi performansı gösterene bağlı olarak. Akıcı / boru hattı stili olan bir uzantı yöntemi olarak ToText'e sahip olmak hala güzel. :-)
Bent Rasmussen

Bu kod ASCII olmayan karakterleri bir boşlukla değiştirir. Bunları çıkartmak için, Seçiniz öğesini seçin:return new string( source.Where( c => c >= min && c <= max ).ToArray() );
Foozinator

@Foozinator Bu kod, ASCII olmayan karakterlerin hangi karakterle değiştirileceğini belirlemenizi sağlar. Varsayılan olarak bir boşluk kullanır, ancak .PureASCII (Char.MinValue) olarak adlandırılırsa, ASCII olmayan tüm '\ 0' ile değiştirilir - bu da onları tam olarak soymaz, ancak benzer sonuçlar verir.
Ulfius

5

normal ifadeye gerek yok. sadece kodlamayı kullan ...

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

5
Bu çalışmıyor. Bu unicode karakterleri şeritlemez, onları? karakter.
David

1
@David haklı. En azından ????nacho??denediğimde aldım : たまねこnachoなちmono 3.4'te
nacho4d

1
Kendi Kodlama sınıfınızı, karakterleri değiştirmek yerine onları kaldıracağınızı başlatabilirsiniz. GetEncoding yöntemine bakın
kkara

4

Aşağıdaki biraz değiştirilmiş aralığı bir veritabanı dışında yorum blokları ayrıştırma için yararlı buldum, bu sekme ve CSV alanı üzülmesine neden olur kaçış karakterleri ile uğraşmak zorunda kalmayacağınız anlamına gelir.

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

Diğer özel karakterlerden veya belirli noktalama işaretlerinden kaçınmak istiyorsanız ascii tablosunu kontrol edin


1
Kimsenin diğer yorumları fark etmemesi durumunda, yazdırılabilir karakterler aslında @ "[^ \ u0020- \ u007E]" olur. Merak ediyorsanız tabloyu görmek için bir link: asciitable.com
scradam

3

Buraya uzun ascii karakterler için bir çözüm aramaya geldim, ama bulamadım. Bulduğum en yakın çözüm bzlm'nin çözümü . Ama bu sadece 127 kadar ASCII Kodu için çalışır (Açıkçası onun kodunda kodlama türünü değiştirebilirsiniz, ama ben anlamak için biraz karmaşık olduğunu düşünüyorum. Bu nedenle, bu sürümü paylaşma). İşte ISO 8859-1 olan 255'e kadar genişletilmiş ASCII kodları için çalışan bir çözüm

Ascii olmayan karakterleri bulur ve çıkarır (255'ten büyük)

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:

İşte kod için çalışan bir keman

Kodlamayı gereksinime göre değiştirin, geri kalanı aynı kalmalıdır.


2
SADECE Ω bu dizeden "Ω c ç ã" kaldırmak için çalışan tek. Çok teşekkür ederim!
Rafael Araújo

2

Bu en iyi performans açısından değil, oldukça basit bir Linq yaklaşımıdır:

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

Dezavantajı, tüm "hayatta kalan" karakterlerin ilk olarak bir tür diziye char[]konmasıdır string;


1

Bu normal ifade ifadesini kullandım:

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

16
Bu, birinin istediği şey değilse, noktalama işaretlerini de kaldırır.
Drew Noakes

1

Bir dosya adındaki bozuk karakterleri filtrelemek için bu normal ifadeyi kullanıyorum.

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

Dosya adları için izin verilen tüm karakterler bu olmalıdır.


1
Hayır! Path.GetInvalidPathChars ve Path.GetInvalidFileNameChars öğelerine bakın . Yani, on binlerce geçerli karakter var.
Tom Blodget

Haklısın Tom. Aslında ortak olanları düşünüyordum, ama parantez ve kıvırcık parantezleri ve bunların hepsini de bıraktım - ^% $ # @! & + =.
user890332
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.