代码之家  ›  专栏  ›  技术社区  ›  p.campbell

用于白名单字符的.NET regex

  •  4
  • p.campbell  · 技术社区  · 15 年前

    考虑一个需要确定 string 包含白名单字符之外的任何字符。

    白名单如下:

    '-.abcdefghijklmnopqrstuvwxyzabbcdefghijklmnopqrstuvwxyz ±±°

    注意:此白名单中需要包含空格和撇号。

    通常这是一个静态方法,但它将被转换为扩展方法。

    private bool ContainsAllWhitelistedCharacters(string input)
    {
      string regExPattern="";// the whitelist
      return Regex.IsMatch(input, regExPattern);
    }
    

    考虑事项:

    感谢所有答疑者的表现评价。性能不是问题。质量、可读性和可维护性是!代码越少,缺陷的可能性越小。

    问题:

    这个白名单regex模式应该是什么?

    4 回复  |  直到 15 年前
        1
  •  4
  •   Kelsey    15 年前

    您可以使用以下方法进行模式匹配:

    ^([\-\.a-zA-Z ÇüéâäàåçêëèïîíìÄÅÉæÆôöòûùÖÜáíóúñÑÀÁÂÃÈÊËÌÍÎÏÐÒÓÔÕØÙÚÛÝßãðõøýþÿ]+)$
    

    使其成为扩展方法:

    public static bool IsValidCustom(this string value)
    {
        string regExPattern="^([\-\.a-zA-Z ÇüéâäàåçêëèïîíìÄÅÉæÆôöòûùÖÜáíóúñÑÀÁÂÃÈÊËÌÍÎÏÐÒÓÔÕØÙÚÛÝßãðõøýþÿ]+)$";
        return Regex.IsMatch(input, regExPattern);
    }
    

    我想不出一种简单的方法来使用扩展字符来实现可维护范围,因为字符的顺序并不明显。

        2
  •  5
  •   Mark Rushakoff    15 年前

    为什么它必须是正则表达式?

    private bool ContainsAllWhitelistedCharacters(string input)
    {
      string whitelist = "abcdefg...";
      foreach (char c in input) {
        if (whitelist.IndexOf(c) == -1)
          return false;
      }
      return true;
    }
    

    如果你不确定如何实现你需要的,并且你还没有分析过代码的那一部分并且发现你需要额外的性能,那么就不需要直接跳到regex中去。

        3
  •  0
  •   Mark Synowiec    15 年前

    我不知道regex后端是如何实现的,但是使用以下内容来匹配除列表之外的任何内容可能是最有效的方法:

    private bool ContainsAllWhitelistedCharacters(string input)
    {
       Regex r = new Regex("[^ your list of chars ]");
       return !r.IsMatch(test)
    }
    
        4
  •  0
  •   ShuggyCoUk    15 年前

    请注意,除非性能 真的? 一个问题,但我想我会指出,即使包括预编译regex,您也可以做得更快一些:

    比较:

    static readonly Regex r = new Regex(
      @"^(['\-\.a-zA-Z ÇüéâäàåçêëèïîíìÄÅÉæÆôöòûùÖÜáíóúñÑ"+
       "ÀÁÂÃÈÊËÌÍÎÏÐÒÓÔÕØÙÚÛÝßãðõøýþÿ]+)$");
    
    public bool IsValidCustom(string value)
    {
      return r.IsMatch(value);
    }
    

    用:

    private bool ContainsAllWhitelistedCharacters(string input)
    {
        foreach (var c in input)
        {
            switch (c)
            {
                case '\u0020': continue; 
                case '\u0027': continue; 
                case '\u002D': continue; 
                case '\u002E': continue; 
                case '\u0041': continue; 
                case '\u0042': continue; 
                case '\u0043': continue; 
                case '\u0044': continue; 
                case '\u0045': continue; 
                case '\u0046': continue; 
                case '\u0047': continue; 
                case '\u0048': continue; 
                case '\u0049': continue; 
                case '\u004A': continue; 
                case '\u004B': continue; 
                case '\u004C': continue; 
                case '\u004D': continue; 
                case '\u004E': continue; 
                case '\u004F': continue; 
                case '\u0050': continue; 
                case '\u0051': continue; 
                case '\u0052': continue; 
                case '\u0053': continue; 
                case '\u0054': continue; 
                case '\u0055': continue; 
                case '\u0056': continue; 
                case '\u0057': continue; 
                case '\u0058': continue; 
                case '\u0059': continue; 
                case '\u005A': continue; 
                case '\u0061': continue; 
                case '\u0062': continue; 
                case '\u0063': continue; 
                case '\u0064': continue; 
                case '\u0065': continue; 
                case '\u0066': continue; 
                case '\u0067': continue; 
                case '\u0068': continue; 
                case '\u0069': continue; 
                case '\u006A': continue; 
                case '\u006B': continue; 
                case '\u006C': continue; 
                case '\u006D': continue; 
                case '\u006E': continue; 
                case '\u006F': continue; 
                case '\u0070': continue; 
                case '\u0071': continue; 
                case '\u0072': continue; 
                case '\u0073': continue; 
                case '\u0074': continue; 
                case '\u0075': continue; 
                case '\u0076': continue; 
                case '\u0077': continue; 
                case '\u0078': continue; 
                case '\u0079': continue; 
                case '\u007A': continue; 
                case '\u00C0': continue; 
                case '\u00C1': continue; 
                case '\u00C2': continue; 
                case '\u00C3': continue; 
                case '\u00C4': continue; 
                case '\u00C5': continue; 
                case '\u00C6': continue; 
                case '\u00C7': continue; 
                case '\u00C8': continue; 
                case '\u00C9': continue; 
                case '\u00CA': continue; 
                case '\u00CB': continue; 
                case '\u00CC': continue; 
                case '\u00CD': continue; 
                case '\u00CE': continue; 
                case '\u00CF': continue; 
                case '\u00D0': continue; 
                case '\u00D1': continue; 
                case '\u00D2': continue; 
                case '\u00D3': continue; 
                case '\u00D4': continue; 
                case '\u00D5': continue; 
                case '\u00D6': continue; 
                case '\u00D8': continue; 
                case '\u00D9': continue; 
                case '\u00DA': continue; 
                case '\u00DB': continue; 
                case '\u00DC': continue; 
                case '\u00DD': continue; 
                case '\u00DF': continue; 
                case '\u00E0': continue; 
                case '\u00E1': continue; 
                case '\u00E2': continue; 
                case '\u00E3': continue; 
                case '\u00E4': continue; 
                case '\u00E5': continue; 
                case '\u00E6': continue; 
                case '\u00E7': continue; 
                case '\u00E8': continue; 
                case '\u00E9': continue; 
                case '\u00EA': continue; 
                case '\u00EB': continue; 
                case '\u00EC': continue; 
                case '\u00ED': continue; 
                case '\u00EE': continue; 
                case '\u00EF': continue; 
                case '\u00F0': continue; 
                case '\u00F1': continue; 
                case '\u00F2': continue; 
                case '\u00F3': continue; 
                case '\u00F4': continue; 
                case '\u00F5': continue; 
                case '\u00F6': continue; 
                case '\u00F8': continue; 
                case '\u00F9': continue; 
                case '\u00FA': continue; 
                case '\u00FB': continue; 
                case '\u00FC': continue; 
                case '\u00FD': continue; 
                case '\u00FE': continue; 
                case '\u00FF': continue;        
            }
            return false;     
        }    return true; // empty string is true    
    }
    

    在对一个通过率约为60%的语料库进行非常快速的测试中,我得到了8倍的速度。

    实际上,它的可读性比不带转义字符的regex要差得多!