我想从字符串中删除所有特殊字符。允许输入A-Z(大写或小写)、数字(0-9)、下划线(_)或点符号(.)。

我有以下,它是有效的,但我怀疑(我知道!)它不是很有效:

    public static string RemoveSpecialCharacters(string str)
    {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < str.Length; i++)
        {
            if ((str[i] >= '0' && str[i] <= '9')
                || (str[i] >= 'A' && str[i] <= 'z'
                    || (str[i] == '.' || str[i] == '_')))
                {
                    sb.Append(str[i]);
                }
        }

        return sb.ToString();
    }

最有效的方法是什么?正则表达式是什么样子的,它与普通字符串操作相比如何?

要清洗的字符串相当短,长度通常在10到30个字符之间。


当前回答

public static string RemoveSpecialCharacters(string str){
    return str.replaceAll("[^A-Za-z0-9_\\\\.]", "");
}

其他回答

我建议创建一个简单的查找表,您可以在静态构造函数中初始化它,以将任何字符组合设置为有效。这让您可以进行快速、单一的检查。

edit

另外,为了提高速度,您需要将StringBuilder的容量初始化为输入字符串的长度。这将避免重新分配。这两种方法结合起来会给你速度和灵活性。

另一个编辑

我认为编译器可能会优化它,但作为风格和效率的问题,我建议foreach而不是for。

我觉得不错。我要做的唯一改进是用字符串的长度初始化StringBuilder。

StringBuilder sb = new StringBuilder(str.Length);

我不确定这是最有效的方法,但对我来说很有效

 Public Function RemoverTildes(stIn As String) As String
    Dim stFormD As String = stIn.Normalize(NormalizationForm.FormD)
    Dim sb As New StringBuilder()

    For ich As Integer = 0 To stFormD.Length - 1
        Dim uc As UnicodeCategory = CharUnicodeInfo.GetUnicodeCategory(stFormD(ich))
        If uc <> UnicodeCategory.NonSpacingMark Then
            sb.Append(stFormD(ich))
        End If
    Next
    Return (sb.ToString().Normalize(NormalizationForm.FormC))
End Function

I had to do something similar for work, but in my case I had to filter all that is not a letter, number or whitespace (but you could easily modify it to your needs). The filtering is done client-side in JavaScript, but for security reasons I am also doing the filtering server-side. Since I can expect most of the strings to be clean, I would like to avoid copying the string unless I really need to. This let my to the implementation below, which should perform better for both clean and dirty strings.

public static string EnsureOnlyLetterDigitOrWhiteSpace(string input)
{
    StringBuilder cleanedInput = null;
    for (var i = 0; i < input.Length; ++i)
    {
        var currentChar = input[i];
        var charIsValid = char.IsLetterOrDigit(currentChar) || char.IsWhiteSpace(currentChar);

        if (charIsValid)
        {
            if(cleanedInput != null)
                cleanedInput.Append(currentChar);
        }
        else
        {
            if (cleanedInput != null) continue;
            cleanedInput = new StringBuilder();
            if (i > 0)
                cleanedInput.Append(input.Substring(0, i));
        }
    }

    return cleanedInput == null ? input : cleanedInput.ToString();
}

我想知道基于regx的替代品(可能是编译的)是否更快。必须测试,有人发现这是~5倍慢。

除此之外,您应该使用预期的长度初始化StringBuilder,这样在中间字符串增长时就不必复制它。

一个好的数字是原始字符串的长度,或者稍低一些(取决于函数输入的性质)。

最后,您可以使用一个查找表(范围0..127)来确定一个字符是否被接受。