Como removo todos os caracteres não alfanuméricos de uma string, exceto o traço?

606

Como removo todos os caracteres não alfanuméricos de uma string, exceto caracteres de traço e espaço?

Luke101
fonte

Respostas:

870

Substitua [^a-zA-Z0-9 -]por uma string vazia.

Regex rgx = new Regex("[^a-zA-Z0-9 -]");
str = rgx.Replace(str, "");
Amarghosh
fonte
79
Vale ressaltar que -deve estar no final da classe de personagem ou ter escapado com uma barra invertida, para evitar ser usado para um intervalo.
Peter Boughton
6
O @Dan define a bandeira global no seu regex - sem isso, apenas substitui a primeira correspondência. Um google rápido deve informar como definir sinalizador global no regex ASP clássico. Caso contrário, procure uma replaceAllfunção em vez de replace.
Amarghosh 22/09/10
20
Aqui está uma versão compilada regex: return Regex.Replace(str, "[^a-zA-Z0-9_.]+", "", RegexOptions.Compiled); Mesma pergunta básica
Paige Watson
13
@MGOwen porque toda vez que você usa "" você está criando um novo objeto devido ao fato de as strings serem imutáveis. Ao usar string.empty, você está reutilizando a instância única necessária para representar uma cadeia vazia, que é mais rápida e mais eficiente.
Brian Scott
17
@BrianScott Eu sei que isso é antigo, mas foi encontrado em uma pesquisa, então eu sinto que isso é relevante. Na verdade, isso depende da versão do .NET em que você está executando. > 2.0 usa ""e string.Emptyexatamente o mesmo. stackoverflow.com/questions/151472/…
Jared
348

Eu poderia ter usado o RegEx, eles podem fornecer uma solução elegante, mas podem causar problemas de desempenho. Aqui está uma solução

char[] arr = str.ToCharArray();

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

Ao usar a estrutura compacta (que não possui FindAll)

Substitua FindAll por 1

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

str = new string(arr);

1 comentário por ShawnFeatherly

ata
fonte
41
nos meus testes, essa técnica foi muito mais rápida. para ser mais preciso, era apenas três vezes mais rápido que a técnica Regex Replace.
Dan
12
A estrutura compacta não possui o FindAll, você pode substituir o FindAll porchar[] arr = str.Where(c => (char.IsLetterOrDigit(c) || char.IsWhiteSpace(c) || c == '-')).ToArray();
ShawnFeatherly
2
alguém já testou isso? Isso não funcionou. --mas isso fez por mim: string str2 = new string (str.Where (c => (char.IsLetterOrDigit (c))). ToArray ());
KevinDeus
48

Podes tentar:

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

Onde sestá sua corda?

josephj1989
fonte
1
OP pediu traço não sublinhado
Sean B
39

Usando System.Linq

string withOutSpecialCharacters = new string(stringWithSpecialCharacters.Where(c =>char.IsLetterOrDigit(c) || char.IsWhiteSpace(c) || c == '-').ToArray());
Zain Ali
fonte
@ Michael É semelhante, mas pelo menos este é um liner, em vez de 3 linhas. Eu diria que é o suficiente para torná-la uma resposta diferente.
Dymas 25/04/19
1
@ Tymas Agora eu concordo que é aceitável, mas não porque o espaço em branco seja diferente. Aparentemente, a parte que é funcionalmente equivalente (apenas os nomes de var diferem) foi editada após a escrita desta resposta.
Michael - Onde está Clay Shirky?
1
@ ZainAli, se você fizer uma edição trivial e fizer um ping, vou reverter meu voto negativo. Peço desculpas por qualquer insinuação de plágio.
Michael - Onde está Clay Shirky?
22

O regex é [^\w\s\-]*:

\sé melhor usar em vez de space ( ), porque pode haver uma guia no texto.

True Soft
fonte
1
a menos que você queira remover as guias.
Matt Ellen
... e novas linhas e todos os outros caracteres considerados "espaço em branco".
Peter Boughton
6
Essa solução é muito superior às soluções acima, pois também suporta caracteres internacionais (não em inglês). <! - language: c # -> string s = "Mötley Crue 日本人: の 氏 名 e Kanji 愛 e Hiragana あ い"; string r = Regex.Replace (s, "[^ \\ w \\ s -] *", ""); O exemplo acima produz r com: Mötley Crue e Kanji e Hiragana
danglund
1
Use @ para escapar \ conversão na string: @ "[^ \ w \ s -] *"
Jakub Pawlinski
1
isso, uhhh ... não remove sublinhados? que é considerado um personagem "palavra" pela implementação regex em toda a criação, mas não é alfanumérico, traço ou espaço ... (?)
Código Jockey
14

Com base na resposta para essa pergunta, criei uma classe estática e as adicionei. Achei que poderia ser útil para algumas pessoas.

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

Em seguida, os métodos podem ser usados ​​como:

string example = "asdf1234!@#$";
string alphanumeric = example.ToAlphaNumericOnly();
string alpha = example.ToAlphaOnly();
string numeric = example.ToNumericOnly();
Ppp
fonte
2
Para o exemplo que você fornece, também seria útil se você fornecesse os resultados de cada um dos métodos.
c-chavez
7

Quer algo rápido?

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

Isso permitirá que você especifique quais caracteres você deseja permitir também.

Zachare Sylvestre
fonte
5

Aqui está uma solução rápida amigável para alocação de heap não-regex que era o que eu estava procurando.

Edição insegura.

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

E para aqueles que não querem usar inseguros ou não confiam no corte do comprimento da string.

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

Fiz uma solução diferente, eliminando os caracteres de controle , que era o meu problema original.

É melhor do que colocar em uma lista todos os caracteres "especiais, mas bons"

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

é mais simples, então eu acho que é melhor!

Pinello
fonte
2

Aqui está um método de extensão usando a resposta @ata como inspiração.

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

ou se você precisar de caracteres adicionais que não sejam hífen ...

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

Eu uso uma variação de uma das respostas aqui. Eu quero substituir espaços por "-" para que seja SEO amigável e também faça letras minúsculas. Também não faça referência a system.web da minha camada de serviços.

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

Aqui está uma versão muito concisa

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

Existe uma maneira muito mais fácil com o Regex.

private string FixString(string str)
{
    return string.IsNullOrEmpty(str) ? str : Regex.Replace(str, "[\\D]", "");
}
Desenvolvimento Syv
fonte
1
só substitui caracteres não numéricos
frostymarvelous