如何从字符串中除了破折号以外删除所有非字母数字字符?

772

我如何从字符串中删除除破折号和空格字符之外的所有非字母数字字符?

13个回答

1081

用空字符串替换[^a-zA-Z0-9 -]

Regex rgx = new Regex("[^a-zA-Z0-9 -]");
str = rgx.Replace(str, "");

100
值得一提的是,为了防止被用作范围表示,- 必须位于字符类结尾或以反斜杠进行转义。 - Peter Boughton
6
请在正则表达式中设置全局标志,否则它只会替换第一个匹配项。快速谷歌搜索应该告诉您如何在经典ASP正则表达式中设置全局标志。否则,寻找一个“replaceAll”函数而不是“replace”。 - Amarghosh
24
这里是一个正则表达式编译版本:return Regex.Replace(str, "[^a-zA-Z0-9_.]+", "", RegexOptions.Compiled);同样的基本问题 - Paige Watson
17
由于字符串是不可变的,每次使用双引号""都会创建一个新的对象。当你使用string.empty时,你是在重用表示空字符串所需的单个实例,这样更快速和更高效。 - Brian Scott
19
@BrianScott 我知道这是旧帖子,但是在搜索中发现,所以我认为这还是相关的。实际上,这取决于您正在运行的.NET版本。> 2.0使用""string.Empty完全相同。https://dev59.com/XXVC5IYBdhLWcg3w51hv - Jared
显示剩余13条评论

394

我本可以使用正则表达式,它们可以提供优美的解决方案,但它们可能会造成性能问题。这里是一个解决方案

char[] arr = str.ToCharArray();

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

当使用紧凑框架(该框架没有FindAll函数)时

1替换FindAll函数

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

str = new string(arr);

1 ShawnFeatherly的评论:


48
在我的测试中,这种技术要快得多。具体来说,它的速度比正则表达式替换技术快了将近3倍。 - Dan
14
紧凑框架没有FindAll方法,你可以用char[] arr = str.Where(c => (char.IsLetterOrDigit(c) || char.IsWhiteSpace(c) || c == '-')).ToArray();替换FindAll。这个表达式可以过滤字符串中的非字母数字、空格和破折号,并将结果存储在字符数组arr中。 - ShawnFeatherly
2
有人测试过这个吗?那完全没用。但是这个对我有效:string str2 = new string(str.Where(c => (char.IsLetterOrDigit(c))).ToArray()); - KevinDeus
作为一行代码 str = string.Concat(str.Where(c => Char.IsLetterOrDigit(c) || Char.IsWhiteSpace(c))) - VDWWD
你将.Where作为一种最后的选择呈现出来,如果Array.FindAll不可用的话,但对我来说,它似乎要简单得多。你有什么理由更喜欢FindAll呢? - Arthur Tacca

80

你可以尝试:

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

其中s是你的字符串。


1
OP 要求破折号而不是下划线。 - Sean B
1
这个不起作用,即使导入了java.util.regex.*,它仍然会给出“找不到符号”的错误。 - David Bandel
11
@DavidBandel 这是C#。 - m47730

51
使用 System.Linq
string withOutSpecialCharacters = new string(stringWithSpecialCharacters.Where(c =>char.IsLetterOrDigit(c) || char.IsWhiteSpace(c) || c == '-').ToArray());

@Michael 这很相似,但至少这是一个一行代码,而不是三行。我认为这足以使它成为另一个答案。 - Dymas
1
@Dymas,我现在同意这是可以接受的,但并不是因为空格不同。显然,在回答写完之后,功能上等效的部分(只有变量名不同)被编辑进来了。 - Michael
1
@ZainAli,如果你进行微不足道的编辑并ping我,我会撤回我的downvote。对于任何剽窃的暗示,我表示歉意。 - Michael

31
正则表达式为[^\w\s\-]*

\s比空格()更好用,因为文本中可能存在制表符。


2
除非您想要删除制表符,否则请返回已翻译的文本。 - Matt Ellen
9
由于此解决方案还支持国际(非英语)字符,所以它比上面的解决方案要优越得多。<!-- language: c# --> string s = "Mötley Crue 日本人: の氏名 and Kanji 愛 and Hiragana あい"; string r = Regex.Replace(s,"[^\w\s-]*","");以上代码将产生以下结果: Mötley Crue 日本人 の氏名 and Kanji 愛 and Hiragana あい - Dan Gøran Lunde
2
在字符串中使用@来转义\转换:@"[^\w\s-]*" - Jakub Pawlinski
@danglund 这些是字母数字字符吗? - minexew
1
它,嗯...不能去除下划线?在所有正则表达式实现中,下划线被视为“单词”字符,但它不是字母数字、破折号或空格... (?) - Code Jockey
显示剩余4条评论

25

基于这个问题的答案,我创建了一个静态类并添加了这些内容。认为它可能对一些人有用。

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
此解决方案与文化相关。 - ndogac

20

想要快速的东西吗?

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

这将使您能够指定您想要允许的字符。


在我看来,这是最好的解决方案。 - suchoss
看起来很干净,但是有点难以指定如何添加空格?我会添加另一个重载,允许使用空格,因为这个方法对单词有效,但不适用于句子或其他空格,例如换行符或制表符。无论如何,解决方案很好。 public static string ToAlphaNumericWithWhitespace(this string self, params char[] allowedCharacters) { return new string(Array.FindAll(self.ToCharArray(), c => char.IsLetterOrDigit(c) || char.IsWhiteSpace(c) || allowedCharacters.Contains(c))); } - Tore Aurstad

7
这是一个非正则表达式堆分配友好的快速解决方案,这正是我所需要的。
不安全版。
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);
}

由于字符串池的存在,您不应更改字符串的内容。 - ndogac

4

我提供了一种不同的解决方案,通过消除控制字符,这是我的原始问题。

这比列出所有“特殊但好”的字符更好。

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

这个技术更简单,所以我认为它更好!


3

这里有一个扩展方法,灵感来自@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);
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接