Wie entferne ich alle nicht alphanumerischen Zeichen mit Ausnahme des Bindestrichs aus einer Zeichenfolge?

606

Wie entferne ich alle nicht alphanumerischen Zeichen aus einer Zeichenfolge mit Ausnahme von Bindestrich- und Leerzeichen?

Luke101
quelle

Antworten:

870

Durch [^a-zA-Z0-9 -]eine leere Zeichenfolge ersetzen .

Regex rgx = new Regex("[^a-zA-Z0-9 -]");
str = rgx.Replace(str, "");
Amarghosh
quelle
79
Erwähnenswert ist, dass -dies am Ende der Zeichenklasse oder mit einem Backslash erfolgen muss, um zu verhindern, dass es für einen Bereich verwendet wird.
Peter Boughton
6
@Dan setzt das globale Flag in Ihrer Regex - ohne das ersetzt es nur die erste Übereinstimmung. Ein kurzer Blick auf Google sollte Ihnen zeigen, wie Sie das globale Flag im klassischen ASP-Regex setzen. Suchen Sie andernfalls nach einer replaceAllFunktion anstelle von replace.
Amarghosh
20
Hier ist eine Regex-kompilierte Version: return Regex.Replace(str, "[^a-zA-Z0-9_.]+", "", RegexOptions.Compiled); Gleiche grundlegende Frage
Paige Watson
13
@MGOwen, weil Sie jedes Mal, wenn Sie "" verwenden, ein neues Objekt erstellen, da Zeichenfolgen unveränderlich sind. Wenn Sie string.empty verwenden, verwenden Sie die einzelne Instanz wieder, die für die Darstellung einer leeren Zeichenfolge erforderlich ist, die schneller und effizienter ist.
Brian Scott
17
@BrianScott Ich weiß, dass dies alt ist, wurde aber bei einer Suche gefunden, daher halte ich dies für relevant. Dies hängt tatsächlich von der Version von .NET ab, unter der Sie ausgeführt werden. > 2.0 verwendet ""& string.Emptygenau das gleiche. stackoverflow.com/questions/151472/…
Jared
348

Ich hätte RegEx verwenden können, sie können eine elegante Lösung bieten, aber sie können Leistungsprobleme verursachen. Hier ist eine Lösung

char[] arr = str.ToCharArray();

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

Bei Verwendung des kompakten Frameworks (das nicht über FindAll verfügt)

Ersetzen Sie FindAll durch 1

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

str = new string(arr);

1 Kommentar von ShawnFeatherly

an einer
quelle
41
In meinen Tests war diese Technik viel schneller. Um genau zu sein, war es knapp dreimal schneller als die Regex Replace-Technik.
Dan
12
Das kompakte Framework hat kein FindAll, Sie können FindAll durchchar[] arr = str.Where(c => (char.IsLetterOrDigit(c) || char.IsWhiteSpace(c) || c == '-')).ToArray();
ShawnFeatherly
2
hat jemand das getestet? Das hat überhaupt nicht funktioniert. - aber das hat für mich getan: string str2 = neuer String (str.Where (c => (char.IsLetterOrDigit (c))). ToArray ());
KevinDeus
48

Du kannst es versuchen:

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

Wo sist deine Schnur?

josephj1989
quelle
1
OP bat um Strich nicht unterstrichen
Sean B
39

Verwenden von System.Linq

string withOutSpecialCharacters = new string(stringWithSpecialCharacters.Where(c =>char.IsLetterOrDigit(c) || char.IsWhiteSpace(c) || c == '-').ToArray());
Zain Ali
quelle
@ Michael Es ist ähnlich, aber zumindest ist dies ein Einzeiler anstatt 3 Zeilen. Ich würde sagen, das reicht aus, um eine andere Antwort zu finden.
Dymas
1
@Dymas Ich stimme jetzt zu, dass es akzeptabel ist, aber nicht, weil das Leerzeichen anders ist. Anscheinend wurde der Teil, der funktional äquivalent ist (nur die Variablennamen unterscheiden sich), bearbeitet, nachdem diese Antwort geschrieben wurde.
Michael - Wo ist Clay Shirky
1
@ZainAli, wenn Sie eine triviale Bearbeitung vornehmen und mich anpingen, werde ich meine Ablehnung rückgängig machen. Ich entschuldige mich für jede Andeutung von Plagiat.
Michael - Wo ist Clay Shirky
22

Der reguläre Ausdruck ist [^\w\s\-]*:

\sist besser als space ( ) zu verwenden, da der Text möglicherweise eine Registerkarte enthält.

True Soft
quelle
1
es sei denn, Sie möchten Tabs entfernen.
Matt Ellen
... und Zeilenumbrüche und alle anderen Zeichen, die als "Leerzeichen" gelten.
Peter Boughton
6
Diese Lösung ist den oben genannten Lösungen weit überlegen, da sie auch internationale (nicht englische) Zeichen unterstützt. <! - language: c # -> string s = "Mötley Crue 日本人: の 氏 Kan und Kanji 愛 und Hiragana あ い"; Zeichenfolge r = Regex.Replace (s, "[^ \\ w \\ s -] *", ""); Das obige produziert r mit: Mötley Crue Kan の 氏 名 und Kanji 愛 und Hiragana あ い
danglund
1
Verwenden Sie @, um \ Konvertierung in Zeichenfolge zu entkommen: @ "[^ \ w \ s -] *"
Jakub Pawlinski
1
es, ähhh ... entfernt keine Unterstriche? Das wird von der Regex-Implementierung in der gesamten Erstellung als "Wort" -Zeichen betrachtet, aber es ist nicht alphanumerisch, Strich oder Leerzeichen ... (?)
Code Jockey
14

Basierend auf der Antwort auf diese Frage habe ich eine statische Klasse erstellt und diese hinzugefügt. Dachte, es könnte für einige Leute nützlich sein.

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

Dann können die Methoden verwendet werden als:

string example = "asdf1234!@#$";
string alphanumeric = example.ToAlphaNumericOnly();
string alpha = example.ToAlphaOnly();
string numeric = example.ToNumericOnly();
Ppp
quelle
2
Für das Beispiel, das Sie bereitstellen, wäre es auch nützlich, wenn Sie die Ergebnisse jeder der Methoden angeben.
C-Chavez
7

Willst du etwas schnelles?

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

Auf diese Weise können Sie angeben, welche Zeichen Sie ebenfalls zulassen möchten.

Zachare Sylvestre
quelle
5

Hier ist eine nicht regex Heap Allocation freundliche schnelle Lösung, nach der ich gesucht habe.

Unsichere Ausgabe.

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

Und für diejenigen, die nicht unsicher verwenden wollen oder dem String-Länge-Hack nicht vertrauen.

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
quelle
4

Ich habe eine andere Lösung gefunden, indem ich die Steuerzeichen entfernt habe , was mein ursprüngliches Problem war.

Es ist besser, als alle "besonderen, aber guten" Zeichen in eine Liste aufzunehmen

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

es ist einfacher, also denke ich es ist besser!

Pinello
quelle
2

Hier ist eine Erweiterungsmethode, bei der @ata answer als Inspiration verwendet wird.

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

oder wenn Sie zusätzliche Zeichen außer Bindestrich benötigen ...

"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
quelle
1

Ich verwende hier eine Variation einer der Antworten. Ich möchte Leerzeichen durch "-" ersetzen, damit es SEO-freundlich ist und auch Kleinbuchstaben enthält. Auch nicht auf system.web aus meiner Serviceschicht verweisen.

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
quelle
0

Hier ist eine sehr knappe Version

myString = myString.replace(/[^A-Za-z0-9 -]/g, "");
GeekyMonkey
quelle
-1

Mit Regex gibt es einen viel einfacheren Weg.

private string FixString(string str)
{
    return string.IsNullOrEmpty(str) ? str : Regex.Replace(str, "[\\D]", "");
}
Syv-Entwicklung
quelle
1
ersetzt nur nicht numerische Zeichen
frostymarvelous