Jak usunąć wszystkie znaki alfanumeryczne z ciągu oprócz myślnika?

606

Jak usunąć z łańcucha wszystkie znaki niealfanumeryczne oprócz znaków myślnika i spacji?

Luke101
źródło

Odpowiedzi:

870

Zamień [^a-zA-Z0-9 -]na pusty ciąg.

Regex rgx = new Regex("[^a-zA-Z0-9 -]");
str = rgx.Replace(str, "");
Amarghosh
źródło
79
Warto wspomnieć, że -musi on znajdować się na końcu klasy postaci lub uciec z odwrotnym ukośnikiem, aby zapobiec użyciu dla zakresu.
Peter Boughton,
6
@Dan ustaw globalną flagę w wyrażeniu regularnym - bez tego po prostu zastępuje pierwsze dopasowanie. Szybki Google powinien powiedzieć, jak ustawić flagę globalną w klasycznym wyrażeniu regularnym ASP. W przeciwnym razie poszukaj replaceAllfunkcji zamiast replace.
Amarghosh,
20
Oto skompilowana wersja wyrażenia regularnego: To return Regex.Replace(str, "[^a-zA-Z0-9_.]+", "", RegexOptions.Compiled); samo podstawowe pytanie
Paige Watson
13
@MGOwen, ponieważ za każdym razem, gdy używasz „”, tworzysz nowy obiekt, ponieważ ciągi są niezmienne. Kiedy używasz string.empty, ponownie używasz pojedynczej instancji wymaganej do przedstawienia pustego ciągu, który jest szybszy, a także bardziej wydajny.
Brian Scott,
17
@BrianScott Wiem, że to jest stare, ale zostało znalezione podczas wyszukiwania, więc uważam, że jest to istotne. To zależy od wersji .NET, na której pracujesz. > 2.0 używa ""i string.Emptydokładnie tak samo. stackoverflow.com/questions/151472/…
Jared
348

Mógłbym użyć RegEx, mogą zapewnić eleganckie rozwiązanie, ale mogą powodować problemy z wydajnością. Oto jedno rozwiązanie

char[] arr = str.ToCharArray();

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

Podczas korzystania z kompaktowego frameworka (który nie ma FindAll)

Zamień FindAll na 1

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

str = new string(arr);

1 komentarz ShawnFeatherly

ata
źródło
41
w moich testach ta technika była znacznie szybsza. mówiąc dokładniej, było to prawie 3 razy szybciej niż technika Regex Replace.
Dan
12
Kompaktowy framework nie ma FindAll, możesz zastąpić FindAllchar[] arr = str.Where(c => (char.IsLetterOrDigit(c) || char.IsWhiteSpace(c) || c == '-')).ToArray();
ShawnFeatherly
2
czy ktoś to przetestował? To w ogóle nie działało. - ale zrobiło to dla mnie: ciąg str2 = nowy ciąg (str.Where (c => (char.IsLetterOrDigit (c))). ToArray ());
KevinDeus
48

Możesz spróbować:

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

Gdzie sjest twój sznurek?

josephj1989
źródło
1
OP poprosił o kreskę, a nie podkreślenie
Sean B
39

Korzystanie z System.Linq

string withOutSpecialCharacters = new string(stringWithSpecialCharacters.Where(c =>char.IsLetterOrDigit(c) || char.IsWhiteSpace(c) || c == '-').ToArray());
Zain Ali
źródło
@Michael Jest podobny, ale przynajmniej jest to jedna linijka, a nie 3 linie. Powiedziałbym, że to wystarczy, aby zmienić odpowiedź.
Dymas,
1
@Dymas Zgadzam się teraz, że jest to dopuszczalne, ale nie dlatego, że biała spacja jest inna. Najwyraźniej część, która jest funkcjonalnie równoważna (różnią się tylko nazwy var), została edytowana po napisaniu tej odpowiedzi.
Michael - Where's Clay Shirky
1
@ZainAli, jeśli zrobisz trywialną edycję i pingujesz mnie, odwrócę moją opinię. Przepraszam za wszelkie insynuacje plagiarne.
Michael - Where's Clay Shirky
22

Wyrażenie regularne to [^\w\s\-]*:

\slepiej jest używać zamiast spacji ( ), ponieważ w tekście może znajdować się tabulator.

True Soft
źródło
1
chyba że chcesz usunąć karty.
Matt Ellen,
... i znaki nowej linii oraz wszystkie inne znaki uważane za „białe znaki”.
Peter Boughton,
6
To rozwiązanie jest znacznie lepsze niż powyższe, ponieważ obsługuje także znaki międzynarodowe (nieanglojęzyczne). <! - language: c # -> string s = "Mötley Crue 日本人: の 氏 名 i Kanji 愛 i Hiragana あ い"; string r = Regex.Replace (s, "[^ \\ w \\ s -] *", ""); Powyższe tworzy r z: Mötley Crue 日本人 の 氏 名 i Kanji 愛 i Hiragana あ い
danglund
1
Użyj @, by uciec \ konwersji w ciągu: @ "[^ \ w \ s -] *"
Jakub Pawliński
1
to nie usuwa podkreślników? który jest uważany za „słowo” przez implementację wyrażenia regularnego w całym stworzeniu, ale nie jest alfanumeryczny, myślnikiem ani spacją… (?)
Code Jockey
14

Na podstawie odpowiedzi na to pytanie utworzyłem klasę statyczną i dodałem je. Pomyślałem, że może być przydatny dla niektórych osób.

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, "");
    }
}

Następnie metody mogą być użyte jako:

string example = "asdf1234!@#$";
string alphanumeric = example.ToAlphaNumericOnly();
string alpha = example.ToAlphaOnly();
string numeric = example.ToNumericOnly();
PPP
źródło
2
W podanym przykładzie przydatne byłoby również podanie wyników każdej z metod.
c-chavez
7

Chcesz coś szybko?

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

To pozwoli ci określić, na które znaki chcesz również zezwolić.

Zachare Sylvestre
źródło
5

Oto szybkie, przyjazne dla alokacji stosów rozwiązanie, które właśnie tego szukałem.

Niebezpieczna edycja.

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';
    }
}

I dla tych, którzy nie chcą używać niebezpiecznych lub nie ufają hackowi długości łańcucha.

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);
}
BjarkeCK
źródło
4

Stworzyłem inne rozwiązanie, eliminując Kontrolę postacie , co było moim pierwotnym problemem.

To lepsze niż umieszczanie na liście wszystkich „specjalnych, ale dobrych” znaków

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

to jest prostsze, więc myślę, że jest lepiej!

Pinello
źródło
2

Oto metoda rozszerzenia wykorzystująca odpowiedź @ata jako inspirację.

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

lub jeśli potrzebujesz dodatkowych znaków innych niż łącznik ...

"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);
    }
}
Aaron Hudon
źródło
1

Używam tutaj wariantu jednej z odpowiedzi. Chcę zastąpić spacje znakiem „-”, więc jest przyjazny dla SEO, a także tworzy małe litery. Również nie odwołuje się do system.web z mojej warstwy usług.

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;
}
Philip Johnson
źródło
0

Oto bardzo zwięzła wersja

myString = myString.replace(/[^A-Za-z0-9 -]/g, "");
GeekyMonkey
źródło
-1

Jest o wiele łatwiejszy sposób z Regex.

private string FixString(string str)
{
    return string.IsNullOrEmpty(str) ? str : Regex.Replace(str, "[\\D]", "");
}
Rozwój Syv
źródło
1
zastępuje tylko znaki nienumeryczne
frostymarvelous