2012-03-30 8 views
0

私はカスタムの電話番号を解析し、正規表現で問題が発生しています:重複するルール

  1. 値マッチング「wtvCode」グループはオプションです。
  2. "countryCode"グループに一致する値はオプションです。
  3. 一部の値では、countryCode規則とareaCityCode規則が重複しています。このような場合、countryCodeが見つからない場合、その式はareaCityCode値を代わりに取得します。

コード例は以下のとおりです。

Regex regex = new Regex(string.Concat(
    "^(", 
    "(?<wtvCode>[A-Z]{3}|)", 
    "([-|/|#| |]|)", 
    "(?<countryCode>[2-9+]{2,5}|)", 
    "([-|/|#| |]|)", 
    "(?<areaCityCode>[0-9]{2,3}|)", 
    "([-|/|#| |]|))", 
    "(?<phoneNumber>(([0-9]{8,18})|([0-9]{3,4}([-|/|#| |]|)[0-9]{4})|([0-9]{4}([-|/|#| |]|)[0-9]{4})|([0-9]{4}([-|/|#| |]|)[0-9]{4}([-|/|#| |]|)[0-9]{1,5})))", 
    "([-|/|#| |]|)", 
    "(?<foo>((A)|(B)))", 
    "([-|/|#| |]|)", 
    "(?<bar>(([1-9]{1,2})|)", 
    ")$" 
)); 

string[] validNumbers = new[] { 
    "11-1234-5678-27-A-2", // missing wtvCode and countryCode 
    "48-1234-5678-27-A-2", // missing wtvCode and countryCode 
    "55-48-1234-5678-27-A-2" // missing wtvCode 
}; 

foreach (string number in validNumbers) { 
    Console.WriteLine("countryCode: {0}", regex.Match(number).Groups["countryCode"].Value); 
    Console.WriteLine("areaCityCode: {0}", regex.Match(number).Groups["areaCityCode"].Value); 
    Console.WriteLine("phoneNumber: {0}", regex.Match(number).Groups["phoneNumber"].Value); 
} 

そのための出力は、次のとおりです。

// First number 
// countryCode:    <- correct 
// areaCityCode: 11   <- correct, but that's because "11" is never a countryCode 
// phoneNumber: 1234-5678-27 <- correct 

// Second number 
// countryCode: 48   <- wrong, should be "" 
// areaCityCode:    <- wrong, should be "48" 
// phoneNumber: 1234-5678-27 <- correct 

// Third number 
// countryCode: 55   <- correct 
// areaCityCode: 48   <- correct 
// phoneNumber: 1234-5678-27 <- correct 

が、私はそれが私のすべての制約をカバーし、COUNTRYCODEとareaCityCodeを台無しにしないような方法でこの正規表現を修正の上、これまで失敗してきました値は両方のルールに一致します。何か案は?

ありがとうございます。


電話国コードの正しい正規表現パターンがここで見つけることができ

更新:https://stackoverflow.com/a/6967885/136381

+1

「55-48-1234-5678-27-A-2」// missing countryCode - > missing wtvCode code? – zishe

答えて

2

まず、私が代わりに空の選択肢のオプションのものを作るために?数量詞を使用することをお勧めします」今使っています。国コードの場合は、?を追加して貪欲でないようにします。そうすれば、最初にareaCityCodeグループの数字の最初の束をキャプチャしようとします。全体の試合が失敗した場合にのみ、戻ってcountryCodeグループを使用します。

Regex regex = new Regex(
    @"^ 
    ((?<wtvCode>[A-Z]{3}) [-/# ])? 
    ((?<countryCode>[2-9+]{2,5}) [-/# ])?? 
    ((?<areaCityCode>[0-9]{2,3}) [-/# ])? 
    (?<phoneNumber> [0-9]{8,18} | [0-9]{3,4}[-/# ][0-9]{4}([-/# ][0-9]{1,5})?) 
    ([-/# ] (?<foo>A|B)) 
    ([-/# ] (?<bar>[1-9]{1,2}))? 
    $", 
    RegexOptions.IgnorePatternWhitespace | RegexOptions.ExplicitCapture); 

あなたが見ることができるように

は、私が最も重要なのは ([-|/|#| |]|)から [-/# ]にスイッチされて、あなたのコードに他のいくつかの変更を加えました。角括弧の中のパイプは、文字通り |と一致します。私はあなたが欲しくないと確信しています。最後のパイプはセパレータをオプションにしました。私は彼らがしないことを願って 実際には、この仕事をはるかに困難にするので、オプションでなければなりません。

+0

あなたのお薦めと同様、あなたの表現はすばらしく見えます。私はそれをテストしています。 –

+0

そしてあなたは "([ - |/|#| |] |)"について正しいです。代わりに区切りパターンを使用しています。 –

1

あなた自身と他のレスポンダーが見落とす2つのことがあります。

最初は、テキストの末尾までの最初の部分よりも多くの必須フィールドがあるため、逆に、つまり右から左に作業する方が理にかなっています。 WTVと国コードの疑念を取り除くことによって、正規表現パーサーが動作するのがはるかに簡単になります(、パターンを書く人が知的に難しいですが、)。

regex(?()|())のif条件を使用します。これにより、シナリオをテストして、1つのマッチパターンを別のパターンに適用することができます。私はブログでRegular Expressions and the If Conditionalと題されたif条件を記述する。以下のパターンは、WTV &国があるかどうかをテストします。それが一致する場合はそれを照合し、そうでなければ任意の国を確認します。また

代わりに、私は以下を示してパターンのコメントを許可するようにIgnorePatternWhitespaceを使用しない理由は、パターン連結した:

string pattern = @" 
^ 
(?([A-Z][^\d]?\d{2,5}(?:[^\d])) # If WTV & Country Code (CC) 
    (?<wtvCode>[A-Z]{3})   # Get WTV & CC 
    (?:[^\d]?) 
    (?<countryCode>\d{2,5}) 
    (?:[^\d])     # Required Break 
    |       # else maybe a CC 
    (?<countryCode>\d{2,5})?  # Optional CC 
    (?:[^\d]?)     # Optional Break 
) 
(?<areaCityCode>\d\d\d?)  # Required area city 
(?:[^\d]?)      # Optional break (OB) 
(?<PhoneStart>\d{4})   # Default Phone # begins 
(?:[^\d]?)      # OB 
(?<PhoneMiddle>\d{4})   # Middle 
(?:[^\d]?)      # OB 
(?<PhoneEnd>\d\d)    # End 
(?:[^\d]?)      # OB 
(?<foo>[AB])     # Foo? 
(?:[^AB]+) 
(?<bar>\d) 
$ 
"; 

    var validNumbers = new List<string>() { 
    "11-1234-5678-27-A-2", // missing wtvCode and countryCode 
    "48-1234-5678-27-A-2", // missing wtvCode and countryCode 
    "55-48-1234-5678-27-A-2", // missing wtvCode 
    "ABC-501-48-1234-5678-27-A-2" // Calling Belize (501) 
}; 

    validNumbers.ForEach(nm => 
       { 
        // IgnorePatternWhitespace only allows us to comment the pattern; does not affect processing 
        var result = Regex.Match(nm, pattern, RegexOptions.IgnorePatternWhitespace | RegexOptions.RightToLeft).Groups; 

        Console.WriteLine (Environment.NewLine + nm); 
        Console.WriteLine("\tWTV code : {0}", result["wtvCode"].Value); 
        Console.WriteLine("\tcountryCode : {0}", result["countryCode"].Value); 
        Console.WriteLine("\tareaCityCode: {0}", result["areaCityCode"].Value); 
        Console.WriteLine("\tphoneNumber : {0}{1}{2}", result["PhoneStart"].Value, result["PhoneMiddle"].Value, result["PhoneEnd"].Value); 

       } 
    ); 

結果:

11-1234-5678-27-A-2 
    WTV code : 
    countryCode : 
    areaCityCode: 11 
    phoneNumber : 1234567827 

48-1234-5678-27-A-2 
    WTV code : 
    countryCode : 
    areaCityCode: 48 
    phoneNumber : 1234567827 

55-48-1234-5678-27-A-2 
    WTV code : 
    countryCode : 55 
    areaCityCode: 48 
    phoneNumber : 1234567827 

ABC-501-48-1234-5678-27-A-2 
    WTV code : ABC 
    countryCode : 501 
    areaCityCode: 48 
    phoneNumber : 1234567827 

注:

  • を国コードと市外局番の間に区切り文字がない場合は、 はありません。アーサーは何が都市で、何が 国であるかを判断することができます。
  • 国が0の場合、元の国コードパターン[2-9]が失敗しました。そこで私はそれを[2-90]に変更しました。
+0

ありがとう、ありがとう。また、[2-90]は電話の国コードでも機能しません。私はここで説明したパターンを使用して終了しました:http://stackoverflow.com/a/6967885/136381 –