Як можна знімати символи, що не належать до ASCII, з рядка? (в C #)


227

Як можна знімати символи, що не належать до ASCII, з рядка? (в C #)


4
Відповідь на відповідь нижче , якщо ви хочете замінити символи, що не належать до ASCII, дивіться натомість цю відповідь .
Бобсон

Відповіді:


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

19
Для тих, хто з нас RegEx викликав виклик, чи не проти виписати простою англійською мовою ваш шаблон RegEx. Іншими словами, "the ^ does this", тощо ...
Метро Смурф

47
@Metro Smurf ^ - не оператор. Він повідомляє регулярному вираженню знайти все, що не відповідає, а не все, що відповідає. \ U #### - \ u #### говорить, які символи збігаються. \ U0000- \ u007F - це еквівалент перших 255 символів у utf-8 або unicode, які завжди є символами ascii. Таким чином, ви співпадаєте з кожним персонажем, який не відповідає (через те, що не є), і замінюєте все, що відповідає.
Гордон Такер

41
Діапазон для символів для друку - 0020-007E, для людей, які шукають регулярних виразів замінити символи, що не друкуються
Мубашар

1
@GordonTucker \ u0000- \ u007F - еквівалент перших 127 символів у utf-8 або unicode, а НЕ перших 225. Дивіться таблицю
full_prog_full

4
@full_prog_full Ось чому я відповів собі приблизно через хвилину, виправляючи себе, сказавши, що це 127, а не 255. :)
Gordon Tucker

125

Ось чисте рішення .NET, яке не використовує регулярні вирази:

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

Це може виглядати громіздко, але це повинно бути інтуїтивно. Він використовує кодування .NET ASCII для перетворення рядка. UTF8 використовується під час перетворення, оскільки він може представляти будь-який з оригінальних символів. Він використовує EncoderReplacementFallback для перетворення будь-якого символу, який не є ASCII, у порожню рядок.


5
Ідеально! Я використовую це для очищення рядка перед збереженням його в документі RTF. Дуже цінується. Набагато простіше зрозуміти, ніж версія Regex.
Натан Пратер

21
Вам справді легше зрозуміти? На мій погляд, всі речі, які насправді не актуальні (резервні копії, перетворення в байти тощо), привертають увагу від того, що відбувається насправді.
bzlm

21
Це як би сказати, що викрутки занадто заплутані, тому я просто використаю молоток.
Брендон

8
@Brandon, насправді, ця методика не справляється краще, ніж інші методи. Тож аналогією було б використання звичайної викрутки Olde замість фантазії iScrewDriver Deluxe 2000. :)
bzlm

10
Одна перевага полягає в тому, що я можу легко замінити ASCII на ISO 8859-1 або іншим кодуванням :)
Акіра Ямамото

38

Я вважаю, що MonsCamus означав:

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

1
IMHO Ця відповідь краща за прийняту відповідь, оскільки вона викреслює контрольні символи.
Dean2690

15

Якщо ви хочете не роздягатись, а фактично перетворювати латинські акценти на символи без акценту, погляньте на це питання: Як я перекладу 8-бітові символи на 7-бітні символи? (тобто від Ü до U)


Я навіть не розумів, що це можливо, але для мене це набагато краще рішення. Я збираюся додати це посилання до коментаря до питання, щоб полегшити пошук інших людей. Дякую!
Бобсон

11

Надихнувшись рішенням регулярної експресії philcruz , я зробив чисте рішення 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();
}

Це неперевірений код.


1
Для тих, хто цього не спіймав, це рішення на основі C # 4.0 LINQ. :)

7
Замість окремого методу ToText (), як щодо заміни рядка 3 PureAscii () на: return new string (source.Select (c => c <min? Nil: c> max? Nil: c) .ToArray ()) ;
agentnega

Або, можливо, ToText як: return (нова рядок (джерело)). ToArray () - залежно від того, що працює найкраще. Досі приємно використовувати ToText як метод розширення - вільний / конвеєрний стиль. :-)
Бент Расмуссен

Цей код замінює символи, що не належать до ASCII, пробілом. Щоб викреслити їх, змініть Виберіть Де:return new string( source.Where( c => c >= min && c <= max ).ToArray() );
Foozinator

@Foozinator Цей код дозволяє вказати, яким символом слід замінити символи, що не належать до ASCII. За замовчуванням він використовує пробіл, але якщо він називається як .PureASCII (Char.MinValue), він замінить усі не-ASCII на '\ 0' - що все ще не точно знімає їх, але подібні результати.
Ульфій

5

немає потреби в регулярному вираженні. просто використовуйте кодування ...

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

5
Це не працює. Це не знімає символів unicode, він замінює їх на? характер.
Девід

1
@David має рацію. Принаймні я отримав, ????nacho??коли спробував: たまねこnachoなちу моно 3,4
nacho4d

1
Ви можете створити власний клас кодування, який замість заміни символів видаляє їх. Дивіться метод GetEncoding: msdn.microsoft.com/en-us/library/89856k4b(v=vs.110).aspx
kkara

4

Я знайшов наступний трохи змінений діапазон, корисний для розбору блоків коментарів із бази даних, це означає, що вам не доведеться боротися з символами табуляції та втечі, що спричинить засмучення поля CSV.

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

Якщо ви хочете уникати інших спеціальних символів чи конкретних пунктуацій, перевірте таблицю ascii


1
Якщо хтось не помітив інших коментарів, символи для друку є насправді @ "[^ \ u0020- \ u007E]". Ось посилання, щоб побачити таблицю, якщо вам цікаво: asciitable.com
scradam

3

Я прийшов сюди шукати рішення для розширених символів ascii, але не зміг його знайти. Найближчий я знайшов рішення bzlm . Але це працює лише для коду ASCII upto 127 (очевидно, ви можете замінити тип кодування в його коді, але я думаю, що це було трохи складно для розуміння. Отже, поділитися цією версією). Ось рішення, яке працює для розширених ASCII-кодів, тобто до 255, що є ISO 8859-1

Він знаходить і викреслює символи, що не належать до асоцій (більше 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:

Ось робоча загадка про код

Замініть кодування відповідно до вимоги, решта повинна залишатися такою ж.


2
Єдиний, хто працював над тим, щоб вилучити ТОЛЬко Ω з цього рядка "Ω c ç ã". Велике спасибі!
Рафаель Арауджо

2

Це не оптимальна ефективність, а досить прямолінійний підхід Linq:

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

Мінус у тому, що всі "вцілілі" символи спочатку поміщаються в масив типу, char[]який потім викидається після того, як stringконструктор більше не використовує його.


1

Я використав цей вираз регулярного вираження:

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

16
Це також знімає розділові знаки, про всяк випадок, коли хтось цього не хоче.
Дрю Ноакс

1

Я використовую цей регулярний вираз для фільтрації поганих символів у імені файлу.

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

Це повинні бути всі символи, дозволені для імен файлів.


1
Ні. Див. Розділи Path.GetInvalidPathChars та Path.GetInvalidFileNameChars . Отже, є десятки тисяч дійсних символів.
Том Блоджет

Ти маєш рацію, Томе. Я насправді думав про загальні, але я залишив дужки та фігурні дужки, а також усі ці - ^% $ # @! & + =.
user890332
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.