C#正则表达式过滤字符

时间:2013-09-18 23:12:50

标签: c# regex string filtering

我在C#中有一个字符串,我想过滤掉(扔掉)所有字符,除了数字,即0到9.例如,如果我有一个字符串,如“5435%$%r3443 _ + _ + ** ╥╡←“,那么输出应该是54353443.如何使用正则表达式或C#中的其他内容来完成?

由于

6 个答案:

答案 0 :(得分:6)

以下是没有正则表达式的示例:

var str = "5435%$% r3443_+_+**╥╡←";
var result = new string(str.Where(o => char.IsDigit(o)).ToArray());
//Or you can make code above slightly more compact, using following syntax:
var result = new string(str.Where(char.IsDigit).ToArray());

从字符串中选择所有内容,即数字字符,并根据选择创建新字符串。

谈论速度。

var sw = new Stopwatch();
var str = "5435%$% r3443_+_+**╥╡←";
sw.Start();
for (int i = 0; i < 100000; i++)
{       
    var result = new string(str.Where(o => char.IsDigit(o)).ToArray());
}
sw.Stop();

Console.WriteLine(sw.ElapsedMilliseconds); // Takes nearly 107 ms 

sw.Reset();
sw.Start();
for (int i = 0; i < 100000; i++)
{
    var s = Regex.Replace(str, @"\D", "");
}
sw.Stop();

Console.WriteLine(sw.ElapsedMilliseconds); //Takes up to 600 ms


sw.Reset();
sw.Start();
for (int i = 0; i < 100000; i++)
{
    var newstr = String.Join("", str.Where(c => Char.IsDigit(c)));
}
sw.Stop();

Console.WriteLine(sw.ElapsedMilliseconds); //Takes up to 109 ms

因此,正则表达式实现可以预测很慢。 Join和new string给出了非常相似的结果,也可能非常依赖于用例。没有用手动字符串循环测试实现,我相信,它可能会给出最好的结果。

<强>更新 还有用于正则表达式的RegexOptions.Compiled选项,用于示例的用法。但是为了测试的清晰度,可以说,编译后的正则表达式在上面提供了近150毫秒的性能提升,这仍然很慢(比其他的慢4倍)。

答案 1 :(得分:6)

这个

你不需要正则表达式
 var newstr = String.Join("", str.Where(c => Char.IsDigit(c)));

答案 2 :(得分:2)

你有什么尝试?

static Regex rxNonDigits = new Regex( @"[^\d]+");
public static string StripNonDigits( string s )
{
  return rxNonDigits.Replace(s,"") ;
}

或者可能更有效率

public static string StripNonDigits( string s )
{
  StringBuilder sb = new StrigBuilder(s.Length) ;
  foreach ( char c in s )
  {
    if ( !char.IsDigit(c) ) continue ;
    sb.Append(c) ;
  }
  return sb.ToString() ;
}

或等效的单行:

public static string StripNonDigits( string s )
{
  return new StringBuilder(s.Length)
         .Append( s.Where(char.IsDigit).ToArray() )
         .ToString()
         ;
}

或者,如果您不关心其他文化的数字并且只关心ASCII十进制数字,您可以保存[可能]昂贵的查找并进行两次比较:

public static string StripNonDigits( string s )
{
  return new StringBuilder(s.Length)
         .Append( s.Where( c => c >= '0' && c <= '9' ).ToArray() )
         .ToString()
         ;
}

应该注意LINQ解决方案几乎肯定需要构建一个中间数组(使用StringBuilder不需要的东西。你也可以使用LINQ聚合:

s.Where( char.IsDigit ).Aggregate(new StringBuilder(s.Length), (sb,c) => sb.Append(c) ).ToString()

有多种方法可以做到!

答案 3 :(得分:1)

<强> CODE:

using System;
using System.Linq;
using System.Text.RegularExpressions;
using System.Diagnostics;

public class Foo
{
    public static void Main()
    {
        string s = string.Empty;
        TimeSpan e;
        var sw = new Stopwatch();

        //REGEX        
        sw.Start();
        for(var i = 0; i < 10000; i++)
        {
            s = "123213!¤%//)54!!#¤!#%13425";
            s = Regex.Replace(s, @"\D", "");
        }
        sw.Stop();
        e = sw.Elapsed;

        Console.WriteLine(s);
        Console.WriteLine(e);

        sw.Reset();

        //NONE REGEX        
        sw.Start();
        for(var i = 0; i < 10000; i++)
        {
            s = "123213!¤%//)54!!#¤!#%13425";
            s = new string(s.Where(c => char.IsDigit(c)).ToArray());
        }
        sw.Stop();
        e = sw.Elapsed;

        Console.WriteLine(s);
        Console.WriteLine(e);
    }
}

<强> OUTPUT:

1232135413425
00:00:00.0564964
1232135413425
00:00:00.0107598

结论:这显然有利于无正则表达式方法来解决这个问题。

答案 4 :(得分:1)

您可以简单地执行以下操作:字符类^内的插入符号([ ])是否定运算符。

var pattern = @"[^0-9]+";
var replaced = Regex.Replace("5435%$% r3443_+_+**╥╡←", pattern, "");

输出:

54353443

答案 5 :(得分:1)

^会从您的匹配中排除某个表达式。与\d一起使用,它与数字0-9匹配,并将其替换为空。

var cleanString = Regex.Replace("123abc,.é", "^\d", "");