Як видалити всі рядкові буквено-цифрові символи з рядка, крім тире?


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.
Amarghosh

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

При використанні Compact Framework (який не має 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.
Dan

12
У компактній рамці немає FindAll, ви можете замінити FindAll наchar[] arr = str.Where(c => (char.IsLetterOrDigit(c) || char.IsWhiteSpace(c) || c == '-')).ToArray();
ShawnFeatherly

2
Хто - небудь перевіряв це? Це зовсім не спрацювало. - але це зробило для мене: string str2 = new string (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
Це рішення набагато перевершує вищезазначені рішення, оскільки воно також підтримує міжнародні (не англійські) символи. <! - мова: c # -> рядок s = "Mötley Crue 日本人: の 氏 名 і Kanji 愛 та Hiragana あ い"; рядок r = Regex.Replace (s, "[^ \\ w \\ s -] *", ""); Вищезгадане виробляє r з: Mötley Crue 日本人 の 氏 名 і Kanji 愛 та Hiragana あ い
danglund

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

1
це, uhhh ... не знімає підкреслення? що вважається символом "слова" шляхом впровадження регулярних виразів у процесі створення, але це не буквено-цифровий, тире чи пробіл ... (?)
Code Jockey

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

Я вирішив інше рішення, усунувши символи Control , що було моєю оригінальною проблемою.

Це краще, ніж покласти в списку все «спеціальні, але хороші» символи

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
замінює лише нечислові символи
frostymarvelous
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.