Как удалить из строки все не алфавитно-цифровые символы, кроме тире?


606

Как удалить из строки все не алфавитно-цифровые символы, кроме тире и пробелов?

Ответы:


870

Заменить [^a-zA-Z0-9 -]на пустую строку.

Regex rgx = new Regex("[^a-zA-Z0-9 -]");
str = rgx.Replace(str, "");

79
Стоит упомянуть, что это -должно быть в конце класса символов или экранировано с обратной косой чертой, чтобы предотвратить использование диапазона.
Питер Боутон

6
@Dan установил глобальный флаг в вашем регулярном выражении - без этого он просто заменяет первое совпадение. Быстрый Google должен сказать вам, как установить глобальный флаг в классическом регулярном выражении ASP. В противном случае ищите replaceAllфункцию вместо replace.
Амаргош

20
Вот скомпилированная версия регулярного выражения: return Regex.Replace(str, "[^a-zA-Z0-9_.]+", "", RegexOptions.Compiled); тот же основной вопрос
Пейдж Уотсон,

13
@MGOwen, потому что каждый раз, когда вы используете "", вы создаете новый объект из-за неизменяемости строк. Когда вы используете string.empty, вы повторно используете единственный экземпляр, необходимый для представления пустой строки, который быстрее и эффективнее.
Брайан Скотт

17
@BrianScott Я знаю, что это старый, но был найден в поиске, поэтому я считаю, что это актуально. На самом деле это зависит от версии .NET, в которой вы работаете. > 2.0 использует ""& string.Emptyточно так же. stackoverflow.com/questions/151472/…
Джаред

348

Я мог бы использовать RegEx, они могут предоставить элегантное решение, но они могут вызвать проблемы с производительностью. Вот одно решение

char[] arr = str.ToCharArray();

arr = Array.FindAll<char>(arr, (c => (char.IsLetterOrDigit(c) 
                                  || char.IsWhiteSpace(c) 
                                  || c == '-')));
str = new string(arr);

При использовании компактного фреймворка (в котором нет FindAll)

Заменить FindAll на 1

char[] arr = str.Where(c => (char.IsLetterOrDigit(c) || 
                             char.IsWhiteSpace(c) || 
                             c == '-')).ToArray(); 

str = new string(arr);

1 комментарий ShawnFeatherly


41
в моем тестировании эта техника была намного быстрее. точнее говоря, это было чуть менее чем в 3 раза быстрее, чем метод Regex Replace.
Дан

12
Компактная структура не имеет FindAll, вы можете заменить FindAll сchar[] arr = str.Where(c => (char.IsLetterOrDigit(c) || char.IsWhiteSpace(c) || c == '-')).ToArray();
ShawnFeatherly

2
кто-нибудь проверял это? Это не сработало вообще. - но это для меня: string str2 = новая строка (str.Where (c => (char.IsLetterOrDigit (c))). ToArray ());
КевинДеус

48

Ты можешь попробовать:

string s1 = Regex.Replace(s, "[^A-Za-z0-9 -]", "");

Где sтвоя строка


1
ОП попросил тире не подчеркнуть
Шон Б

39

Использование System.Linq

string withOutSpecialCharacters = new string(stringWithSpecialCharacters.Where(c =>char.IsLetterOrDigit(c) || char.IsWhiteSpace(c) || c == '-').ToArray());

@Michael Это похоже, но, по крайней мере, это один вкладыш, а не 3 строки. Я бы сказал, что этого достаточно, чтобы сделать другой ответ.
Димас

1
@Dymas Теперь я согласен, что это приемлемо, но не потому, что пробелы отличаются. Очевидно, что часть, которая является функционально эквивалентной (отличаются только имена переменных), была отредактирована после написания этого ответа.
Майкл - Где Клэй Ширки

1
@ZainAli, если вы сделаете тривиальное редактирование и отправите мне пинг, я откажусь от своего отрицательного ответа. Я прошу прощения за любые инсинуации плагиата.
Майкл - Где Клэй Ширки

22

Регулярное выражение [^\w\s\-]*:

\sЛучше использовать вместо пробела ( ), потому что в тексте может быть вкладка.


1
если вы не хотите удалять вкладки.
Мэтт Эллен

... и переводы строк, и все остальные символы считаются "пробелами".
Питер Боутон

6
Это решение намного превосходит вышеуказанные решения, поскольку оно также поддерживает международные (не английские) символы. <! - language: c # -> string s = "Мотли Крю 日本人: の 氏 名 и Кандзи 愛 и Хирагана あ い"; string r = Regex.Replace (s, "[^ \\ w \\ s -] *", ""); Вышеизложенное производит г с: Мотли Крю 日本人 の 氏 名 и Кандзи 愛 и Хирагана あ い
danglund

1
Используйте @, чтобы избежать \ преобразования в строке: @ "[^ \ w \ s -] *"
Якуб Павлински

1
это, эээ ... не удаляет подчеркивания? это считается "словом" символом при реализации регулярного выражения во время создания, но это не алфавитно-цифровой, тире или пробел ... (?)
Код Жокей

14

Основываясь на ответе на этот вопрос, я создал статический класс и добавил их. Думал, что это может быть полезно для некоторых людей.

public static class RegexConvert
{
    public static string ToAlphaNumericOnly(this string input)
    {
        Regex rgx = new Regex("[^a-zA-Z0-9]");
        return rgx.Replace(input, "");
    }

    public static string ToAlphaOnly(this string input)
    {
        Regex rgx = new Regex("[^a-zA-Z]");
        return rgx.Replace(input, "");
    }

    public static string ToNumericOnly(this string input)
    {
        Regex rgx = new Regex("[^0-9]");
        return rgx.Replace(input, "");
    }
}

Тогда методы можно использовать как:

string example = "asdf1234!@#$";
string alphanumeric = example.ToAlphaNumericOnly();
string alpha = example.ToAlphaOnly();
string numeric = example.ToNumericOnly();

2
Для примера, который вы предоставляете, было бы также полезно, если бы вы предоставили результаты каждого из методов.
c-chavez

7

Хотите что-нибудь быстрое?

public static class StringExtensions 
{
    public static string ToAlphaNumeric(this string self, params char[] allowedCharacters)
    {
        return new string(Array.FindAll(self.ToCharArray(), c => char.IsLetterOrDigit(c) || allowedCharacters.Contains(c)));
    }
}

Это позволит вам указать, какие символы вы также хотите разрешить.


5

Вот быстрое решение для выделения кучи без регулярных выражений, которое я и искал.

Небезопасное издание.

public static unsafe void ToAlphaNumeric(ref string input)
{
    fixed (char* p = input)
    {
        int offset = 0;
        for (int i = 0; i < input.Length; i++)
        {
            if (char.IsLetterOrDigit(p[i]))
            {
                p[offset] = input[i];
                offset++;
            }
        }
        ((int*)p)[-1] = offset; // Changes the length of the string
        p[offset] = '\0';
    }
}

И для тех, кто не хочет использовать небезопасный или не доверяет взлому длины строки.

public static string ToAlphaNumeric(string input)
{
    int j = 0;
    char[] newCharArr = new char[input.Length];

    for (int i = 0; i < input.Length; i++)
    {
        if (char.IsLetterOrDigit(input[i]))
        {
            newCharArr[j] = input[i];
            j++;
        }
    }

    Array.Resize(ref newCharArr, j);

    return new string(newCharArr);
}

4

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

Это лучше, чем занести в список все «особые, но хорошие» символы

char[] arr = str.Where(c => !char.IsControl(c)).ToArray();    
str = new string(arr);

это проще, так что я думаю, что лучше!


2

Вот метод расширения, использующий ответ @ata для вдохновения.

"hello-world123, 456".MakeAlphaNumeric(new char[]{'-'});// yields "hello-world123456"

или если вам нужны дополнительные символы, кроме дефиса ...

"hello-world123, 456!?".MakeAlphaNumeric(new char[]{'-','!'});// yields "hello-world123456!"


public static class StringExtensions
{   
    public static string MakeAlphaNumeric(this string input, params char[] exceptions)
    {
        var charArray = input.ToCharArray();
        var alphaNumeric = Array.FindAll<char>(charArray, (c => char.IsLetterOrDigit(c)|| exceptions?.Contains(c) == true));
        return new string(alphaNumeric);
    }
}

1

Я использую вариант одного из ответов здесь. Я хочу заменить пробелы на "-", чтобы оптимизировать его для SEO, а также использовать строчные буквы. Также не ссылка system.web из моего уровня услуг.

private string MakeUrlString(string input)
{
    var array = input.ToCharArray();

    array = Array.FindAll<char>(array, c => char.IsLetterOrDigit(c) || char.IsWhiteSpace(c) || c == '-');

    var newString = new string(array).Replace(" ", "-").ToLower();
    return newString;
}


-1

Есть гораздо более простой способ с Regex.

private string FixString(string str)
{
    return string.IsNullOrEmpty(str) ? str : Regex.Replace(str, "[\\D]", "");
}

1
заменяет только нечисловые символы
морозный,
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.