1

これは、日付の検証を行うためのコードを使用する最善の方法についての質問ではないことに注意してください。これは、いくつかの試行とエラー、および他の人々があなたに感謝することを通じて、正規表現についてさらに学ぶことについての質問です。

私は最近正規表現で多くの仕事をしています(率直に言って私はそれらを吸います)しかし私は多くを学んでいます、そして誰かが特定の正規表現について彼らの専門家の意見を与えることができるかどうか疑問に思います。

現在、私は.NET 4.0を使用するためにかなり大規模なプロジェクトの移行に取り組んでいます。これには、多くのクラスと名前空間にまたがる多くの解析およびデータ操作メソッドがあります...ただし、解析と検証のすべてではない大部分がIndexOf()呼び出しが多いループの場合は大きく不格好です。

私は、正規表現、LINQ、および拡張メソッドの組み合わせを非常にうまく使用して、解析および検証メソッドを大幅に簡素化および明確化しています。

試行錯誤とRegexBuddyは、学習曲線を大幅に改善しました。

さて、私の実際の質問に移りましょう。

非常に緩い検証ですが、私は単純な日付検証の更新に取り組んでいました

private static bool isLikeVCardDate(string value_Renamed)
{
  if (value_Renamed == null)
  {
    return true;
  }
  // Not really sure this is true but matches practice
  // Mach YYYYMMDD
  if (isStringOfDigits(value_Renamed, 8))
  {
    return true;
  }
  // or YYYY-MM-DD
  return value_Renamed.Length == 10 && value_Renamed[4] == '-' && value_Renamed[7] == '-' && isSubstringOfDigits(value_Renamed, 0, 4) && isSubstringOfDigits(value_Renamed, 5, 2) && isSubstringOfDigits(value_Renamed, 8, 2);
}

その機能を一致させたい場合は、の単純な正規表現

private static bool isLikeVCardDate(string value_Renamed)
{
  return Regex.IsMatch(value_Renamed, @"\d{4}-?\d{2}-?d{2}");
}

要件を満たします

しかし、日付が完全に有効な日付、うるう年、9ヤード全体の月の日であることを検証するにはどうすればよいか考えさせられました。

正規表現を使用した日付の検証に関する他の投稿があることを知っています私は誰かが私に答えを与えることに興味がありません私はそれを機能させていますまたはそれを改善します。

これはおそらく正規表現を使用する実際のアプリケーションの最良の例ではないことを私は知っています。私はここで学ぼうとしていることを忘れないでください。助けていただければ幸いです。

これが私が思いついた正規表現です

読みやすくするために「タブ付き」ビューに貼り付けているメモです。実際の正規表現にはスペースや新しい行がありません。

さらに、名前付きキャプチャグループではないものはすべて非キャプチャグループです(正規表現の分析が必要なため、スペースを節約するために省略しました)

(
 (?<YEAR>((([0][48])|([13579][26])|([2468][048]))00)|(\d{2}(([0][48])|([13579][26])|([2468][048]))))
 -?
 (
  (
   (?<MONTH>(0[13578])|( 1[02]))
   -?
   (?<DAY>(0[1-9])|([12][0-9])|(3[01]))
  )
  |
  (
   (?<MONTH>(0[469])|11)
   -?
   (?<DAY>(0[1-9])|([12][0-9])|30)
  )
  |
  (
   (?<MONTH>02)
   -?
   (?<DAY>(0[1-9])|([12][0-9]))
  )
 )
)
|
(
 (?<YEAR>\d{4})
 -?
 (
  (
   (?<MONTH>(0[13578])|(1[02]))
   -?
   (?<DAY>(0[1-9])|([12][0-9])|(3[01]))
  )
  |
  (
   (?<MONTH>(0[469])|11)
   -?
   (?<DAY>(0[1-9])|([12][0-9])|30)
  )
  |
  (
   (?<MONTH>02)
   -?
   (?<DAY>(0[1-9])|(1[0-9])|(2[0-8]))
  ) 
 )
)

これが私の思考プロセスです

  1. 日は月を基準にしています4、6、9、11は30日です| 1,3,5,7,8,10,12は31で、2は28または29です。

  2. うるう年は、100で割り切れない限り、4で割り切れます。ただし、400で割り切れる場合に限ります。

    1. これと、数値としての最後の2桁が4で割り切れる場合、任意の数値が4で割り切れるという事実に基づいています。

    2. 4から96までの数字を書き出す私は0(4,8)、{偶数> 0}(0,4,8)、{奇数}(2,6)の繰り返しパターンを使用しました

    3. 400年のうるう年のテストでは、年の最初の2桁が適用可能であるため、上記の#2と同じパターンを使用できます。

  3. うるう年の要件があるため、正規表現では、うるう年の日付とうるう年ではない日付に対して2つの別々のキャプチャが必要です。

今、私の仮定はすべて間違っていて、そこに明白になっている可能性がありますが、これまでのところ、正規表現をどれだけ理解しているかを思いつくことができます

繰り返しますが、私は必死に頭を包み込む必要があるので、正規表現を改善するための助けを探しています。

この質問を読むために時間を費やしてくださった皆さん、本当にありがとうございました。

4

1 に答える 1

2

正規表現を学ぶための演習としてこれを行っていることを理解しているので、これらの他の質問への回答の例がどのように機能するかを楽しんでください。

もちろん、正規表現について学ぶための最も重要な教訓の1つは、正規表現を使用しない場合です。結果として、あなたが投稿した例についての詳細なフィードバックを得るのに苦労するかもしれないと思います。ここでの持ち帰りの教訓は、複雑な正規表現を書くことを楽しむ人もいれば、それらを読む(または拡張または修正する)ことを楽しむ人はほとんどいないということです。

于 2012-06-07T07:30:11.860 に答える