2009-08-20 20 views
4

stringにホワイトリスト文字以外の文字が含まれているかどうかを判断するアルゴリズムを検討してください。ホワイトリスト文字の.NET正規表現

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

注:スペースとアポストロフィがこのホワイトリストに含まれる必要がある

ホワイトリストは、次のようになります。

通常、これは静的メソッドですが、拡張メソッドに変換されます。

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

考慮事項:すべての回答者に、パフォーマンス・コメントの

感謝。パフォーマンスは問題ではありません。品質、可読性、および保守性は!少ないコード=不具合の可能性が低い、IMO。

質問:

このホワイトリストの正規表現パターンは何をすべきですか?

+2

そのような 'string'の拡張メソッドを作成した場合、すべての文字列に含まれているものと含まれていないもののホワイトリストの対象となりますが、そうではありません。 –

+0

@ 28:コメントいただきありがとうございます。私はこのメソッドがすべての 'string'メンバーに利用可能であることを理解しています。ユーティリティメソッドとしての実装と同じように、拡張メソッドを賢明に呼び出すことは開発者次第です。 –

+0

@pcampbell:コンストラクタでチェックインした不正な文字を含まないことがわかっている文字列を保持する不変構造体を作成する必要があります。そうすれば、 'Path'クラスと違って、悪い文字のO(n)チェックを行うことなく文字列を操作することができます。 –

答えて

4

あなたはパターンマッチ、以下のものを使用してできます

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

それに拡張メソッド作る:私は拡張文字と保守性の範囲を行う簡単な方法を考えることはできません

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

文字の順序は明白ではないためです。

+0

文字セットに関する注意。 – Havenard

+0

私は上記のパターンは空白の値を許可するために少し微調整が必​​要になると思います。 また、サポートされているすべての言語のアルファベットを列挙する代わりに、組み込みの文字クラス "\ w"を使用することを検討してください。これにより、アンダースコアと数字が表示され、2番目のRegExが除外される必要がありますが、文字クラスを再作成しようとすると、多くの潜在的なメンテナンスが削減されます。 – richardtallent

+1

私はそれをテストしており、スペースで動作します。それは値のハードコードされたリストです、スペースはZの後ろに含まれています。範囲はa-zとA-Zからの文字です – Kelsey

5

なぜ正規表現にする必要がありますか?

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

あなたが必要なものを実装する方法がわからないと、あなたがプロファイリングそのコードのセクションと、あなたが余分なパフォーマンスを必要と判明していない場合は正規表現の中にまっすぐにジャンプする必要はありません。

+0

うーん...これはうまくいかないので、すべてのupvotesなぜですか?文字列に無効な文字が含まれていると、それは捕捉されません。 – Kelsey

+0

ありがとうございました。残念ながら、この提案の 'IndexOfAny'は' _ 'や' 5 'のようなホワイトリストにない文字をフィルターで取り除いて返しません。 –

+0

ええ、私はちょうどそれを実現し、それを取り出しました - それは本当にアップホントを得てはいけません。誰もそれを読んでも、誰もそれを読んでいません:X –

0

私は正規表現のバックエンドが実装されているのか分からないが、それはあなたのリスト以外に何のために一致させるために、以下の使用する最も効率的であるかもしれない:私はしない限り、これはお勧めしません

private bool ContainsAllWhitelistedCharacters(string input) 
{ 
    Regex r = new Regex("[^ your list of chars ]"); 
    return !r.IsMatch(test) 
} 
+6

二重ネガは紛らわしいことではありません。 –

+0

私は同意する、私はこのようにすることをお勧め* *それはより効率的な正規表現のC#であると仮定します。これが真実かどうか誰にも分かりますか?私は答えに興味があります。 –

0

注意をパフォーマンスは本当に問題ですが、私は、私も正規表現をプリコンパイルを含め、あなたはかなり速く行うことができます、ということを指摘だろうと思った:

が比較:

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

public bool IsValidCustom(string value) 
{ 
    return r.IsMatch(value); 
} 
私はこのアプローチには8スピードアップの要因について、取得、約60%の合格率を持つ単語のコーパス上の非常に迅速なテストで

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  
} 

:と10

エスケープ文字のない正規表現よりも読みにくいです。