Comment supprimer tous les caractères non alphanumériques d'une chaîne à l'exception du tiret?

606

Comment supprimer tous les caractères non alphanumériques d'une chaîne à l'exception des tirets et des espaces?

Luke101
la source

Réponses:

870

Remplacez [^a-zA-Z0-9 -]par une chaîne vide.

Regex rgx = new Regex("[^a-zA-Z0-9 -]");
str = rgx.Replace(str, "");
Amarghosh
la source
79
Il convient de mentionner que cela -doit être à la fin de la classe de personnage, ou échappé avec une barre oblique inverse, pour éviter d'être utilisé pour une plage.
Peter Boughton
6
@Dan a défini le drapeau global dans votre expression régulière - sans cela, il remplace simplement la première correspondance. Un rapide google devrait vous dire comment définir un indicateur global dans une expression régulière ASP classique. Sinon, recherchez une replaceAllfonction au lieu de replace.
Amarghosh
20
Voici une version compilée des expressions rationnelles: return Regex.Replace(str, "[^a-zA-Z0-9_.]+", "", RegexOptions.Compiled); Même question de base
Paige Watson
13
@MGOwen parce que chaque fois que vous utilisez "" vous créez un nouvel objet car les chaînes sont immuables. Lorsque vous utilisez string.empty, vous réutilisez l'instance unique requise pour représenter une chaîne vide qui est plus rapide et plus efficace.
Brian Scott
17
@BrianScott Je sais que c'est vieux, mais j'ai été trouvé dans une recherche, donc je pense que c'est pertinent. Cela dépend en fait de la version de .NET sous laquelle vous exécutez. > 2.0 utilise ""et string.Emptyexactement la même chose. stackoverflow.com/questions/151472/…
Jared
348

J'aurais pu utiliser RegEx, ils peuvent fournir une solution élégante mais ils peuvent causer des problèmes de performance. Voici une solution

char[] arr = str.ToCharArray();

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

Lors de l'utilisation du cadre compact (qui n'a pas FindAll)

Remplacez FindAll par 1

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

str = new string(arr);

1 Commentaire par ShawnFeatherly

à
la source
41
dans mes tests, cette technique était beaucoup plus rapide. pour être précis, il était un peu moins de 3 fois plus rapide que la technique Regex Replace.
Dan
12
Le cadre compact n'a pas FindAll, vous pouvez remplacer FindAll parchar[] arr = str.Where(c => (char.IsLetterOrDigit(c) || char.IsWhiteSpace(c) || c == '-')).ToArray();
ShawnFeatherly
2
quelqu'un a-t-il testé cela? Cela n'a pas fonctionné du tout. --mais cela a fait pour moi: chaîne str2 = nouvelle chaîne (str.Where (c => (char.IsLetterOrDigit (c))). ToArray ());
KevinDeus
48

Tu peux essayer:

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

sest ta chaîne.

josephj1989
la source
1
OP a demandé un tiret sans souligner
Sean B
39

Utilisation de System.Linq

string withOutSpecialCharacters = new string(stringWithSpecialCharacters.Where(c =>char.IsLetterOrDigit(c) || char.IsWhiteSpace(c) || c == '-').ToArray());
Zain Ali
la source
@Michael C'est similaire mais au moins c'est une ligne, plutôt que 3 lignes. Je dirais que cela suffit pour en faire une réponse différente.
Dymas
1
@Dymas Je suis maintenant d'accord pour dire que c'est acceptable, mais pas parce que l'espace est différent. Apparemment, la partie qui est fonctionnellement équivalente (seuls les noms var diffèrent) a été modifiée après la rédaction de cette réponse.
Michael - Où est Clay Shirky le
1
@ZainAli, si vous effectuez une modification triviale et que vous me cinglez, j'inverserai mon downvote. Je m'excuse pour toute insinuation de plagiaire.
Michael - Où est Clay Shirky le
22

Le regex est [^\w\s\-]*:

\sest préférable d'utiliser à la place de space ( ), car il peut y avoir un onglet dans le texte.

True Soft
la source
1
sauf si vous souhaitez supprimer des onglets.
Matt Ellen
... et les nouvelles lignes, et tous les autres personnages considérés comme des "espaces blancs".
Peter Boughton
6
Cette solution est de loin supérieure aux solutions ci-dessus car elle prend également en charge les caractères internationaux (non anglais). <! - language: c # -> string s = "Mötley Crue 日本人: の 氏 名 et Kanji 愛 et Hiragana あ い"; chaîne r = Regex.Replace (s, "[^ \\ w \\ s -] *", ""); Ce qui précède produit r avec: Mötley Crue 日本人 の 氏 名 et Kanji 愛 et Hiragana あ い
danglund
1
Utilisez @ pour échapper \ conversion dans la chaîne: @ "[^ \ w \ s -] *"
Jakub Pawlinski
1
ça, euhhh ... ne supprime pas les traits de soulignement? qui est considéré comme un caractère "mot" par l'implémentation de l'expression rationnelle à travers la création, mais ce n'est pas alphanumérique, tiret ou espace ... (?)
Code Jockey
14

Sur la base de la réponse à cette question, j'ai créé une classe statique et ajouté ces derniers. Je pensais que cela pourrait être utile pour certaines personnes.

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

Ensuite, les méthodes peuvent être utilisées comme:

string example = "asdf1234!@#$";
string alphanumeric = example.ToAlphaNumericOnly();
string alpha = example.ToAlphaOnly();
string numeric = example.ToNumericOnly();
Ppp
la source
2
Pour l'exemple que vous fournissez, il serait également utile de fournir les résultats de chacune des méthodes.
c-chavez
7

Vous voulez quelque chose de rapide?

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

Cela vous permettra également de spécifier les caractères que vous souhaitez autoriser.

Zachare Sylvestre
la source
5

Voici une solution rapide conviviale d'allocation de tas non regex qui était ce que je cherchais.

Édition non sécurisée.

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

Et pour ceux qui ne veulent pas utiliser dangereux ou ne font pas confiance au hack de longueur de chaîne.

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
la source
4

J'ai fait une solution différente, en éliminant les caractères de contrôle , ce qui était mon problème d'origine.

C'est mieux que de mettre dans une liste tous les caractères "spéciaux mais bons"

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

c'est plus simple, donc je pense que c'est mieux!

Pinello
la source
2

Voici une méthode d'extension utilisant la réponse @ata comme source d'inspiration.

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

ou si vous avez besoin de caractères supplémentaires autres que le trait d'union ...

"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
la source
1

J'utilise ici une variante de l'une des réponses. Je veux remplacer les espaces par "-" afin que son référencement soit convivial et également en minuscules. Ne référence pas non plus system.web à partir de ma couche de services.

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
la source
0

Voici une version très concise

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

Il y a un moyen beaucoup plus simple avec Regex.

private string FixString(string str)
{
    return string.IsNullOrEmpty(str) ? str : Regex.Replace(str, "[\\D]", "");
}
Développement Syv
la source
1
remplace uniquement les caractères non numériques
frostymarvelous