Как вы можете удалить не-ASCII символы из строки? (в C #)

227

Как вы можете удалить не-ASCII символы из строки? (в C #)

philcruz
источник
4
За ответ sinelaw в поле ниже , если же вы хотите , чтобы заменить не-ASCII символов, см этот ответ вместо .
Бобсон

Ответы:

414
string s = "søme string";
s = Regex.Replace(s, @"[^\u0000-\u007F]+", string.Empty);
philcruz
источник
19
Для тех из нас, кого RegEx бросил вызов, не могли бы вы написать на английском языке свой шаблон RegEx. Другими словами, «^ делает это» и т. Д.
Метро Смурф
47
@Metro Smurf ^ - это не оператор. Он говорит регулярному выражению найти все, что не соответствует, вместо всего, что соответствует. \ U #### - \ u #### говорит, какие символы совпадают. \ U0000- \ u007F является эквивалентом первых 255 символов в utf-8 или unicode, которые всегда являются символами ascii. Таким образом, вы соответствуете каждому не ascii символу (из-за не) и делаете замену на все, что соответствует.
Гордон Такер
41
Диапазон для печатаемых символов - 0020-007E, для людей, которые ищут регулярные выражения для замены непечатаемых символов
Мубашар
1
@GordonTucker \ u0000- \ u007F является эквивалентом первых 127 символов в utf-8 или unicode, а НЕ первых 225. См. Таблицу
full_prog_full
4
@full_prog_full Именно поэтому я примерно через минуту ответил себе, исправляя себя, говоря, что это 127, а не 255. :)
Гордон Такер
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 символа в пустую строку.

bzlm
источник
5
Отлично! Я использую это для очистки строки перед сохранением в RTF-документ. Очень ценится. Гораздо проще понять, чем версия Regex.
Натан Пратер
21
Вам правда легче понять? Для меня все вещи, которые не очень актуальны (запасные варианты, преобразования в байты и т. Д.), Отвлекают внимание от того, что на самом деле происходит.
bzlm
21
Это все равно, что сказать, что отвертки слишком запутаны, поэтому я просто использую молоток.
Брэндон
8
@ Брэндон, на самом деле, этот метод не делает работу лучше, чем другие методы. Таким образом, аналогия будет использовать обычную отвертку вместо оригинальной iScrewDriver Deluxe 2000. :)
bzlm
10
Одним из преимуществ является то, что я могу легко заменить ASCII на ISO 8859-1 или другую кодировку :)
Акира Ямамото,
38

Я считаю, что MonsCamus имел в виду:

parsememo = Regex.Replace(parsememo, @"[^\u0020-\u007E]", string.Empty);
мистифицировать
источник
1
ИМХО Этот ответ лучше, чем принятый ответ, потому что он удаляет контрольные символы.
декан 2690
15

Если вы хотите не вырезать, а на самом деле конвертировать символы латинского акцентирования в символы без акцента, взгляните на этот вопрос: как мне перевести 8-битные символы в 7-битные символы? (то есть от Ü до U)

sinelaw
источник
Я даже не осознавал, что это возможно, но для меня это намного лучшее решение. Я собираюсь добавить эту ссылку в комментарий к этому вопросу, чтобы другим людям было легче его найти. Спасибо!
Бобсон
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
Для тех, кто этого не понял, это решение на основе LINQ для C # 4.0. :)
7
Вместо отдельного метода ToText (), как насчет замены строки 3 функции PureAscii () на: возвращение новой строки (source.Select (c => c <min? Nil: c> max? Nil: c) .ToArray ()) ;
Агентнега
Или, возможно, ToText as: return (новая строка (источник)). ToArray () - в зависимости от того, что работает лучше всего. Все еще хорошо иметь ToText в качестве метода расширения - свободный / конвейерный стиль. :-)
Бент Расмуссен
Этот код заменяет символы, не входящие в ASCII, пробелом. Чтобы удалить их, измените Select на Where: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));
RJP
источник
5
Это не работает. Это не удаляет символы Юникода, оно заменяет их на? персонаж.
Дэвид
1
@ Дэвид прав. По крайней мере, я получил, ????nacho??когда я пытался: たまねこnachoなちв моно 3,4
nacho4d
1
Вы можете создать свой собственный класс Encoding, который вместо замены символов удаляет их. См. Метод GetEncoding: msdn.microsoft.com/en-us/library/89856k4b(v=vs.110).aspx
kkara
4

Я обнаружил, что следующий слегка измененный диапазон полезен для анализа блоков комментариев из базы данных, это означает, что вам не придется бороться с символами табуляции и экранирования, которые могут привести к нарушению поля CSV.

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

Если вы хотите избежать других специальных символов или знаков препинания, проверьте таблицу ascii

MonsCamus
источник
1
Если кто-то еще не заметил другие комментарии, печатные символы на самом деле являются @ "[^ \ u0020- \ u007E]". Вот ссылка для просмотра таблицы, если вам интересно: asciitable.com
scradam
3

Я пришел сюда в поисках решения для расширенных символов ascii, но не смог его найти. Самое близкое, что я нашел, - это решение bzlm . Но это работает только для кода ASCII до 127 (очевидно, вы можете заменить тип кодирования в его коде, но я думаю, что это было немного сложно понять. Следовательно, поделиться этой версией). Вот решение, которое работает для расширенных кодов ASCII, т.е. до 255, что является ISO 8859-1

Он находит и удаляет символы не-ascii (больше 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\\:_\- ]", "")

Это должны быть все символы, разрешенные для имен файлов.

user890332
источник
1
Нет. Смотрите Path.GetInvalidPathChars и Path.GetInvalidFileNameChars . Итак, есть десятки тысяч действительных символов.
Том Блоджет
Вы правы, Том. Я на самом деле думал об общих, но я исключил скобки и фигурные скобки, а также все эти - ^% $ # @! & + =.
user890332