none
パターンマッチング 正規表現:半角大文字アルファベットと、半角数字、それぞれ一文字以上含めば True RRS feed

  • 質問

  • いつも大変にお世話になっております。

    半角のアルファベット[A-Z]と、半角の数字[0-9]ともに、それぞれ1文字以上を含む判定をしたいのですが、パターンマッチングが分からず行き詰っております。どうかご教示いただけませんでしょうか。

    出したい答え
     A1 → True、AA11 → True、AAA → False、111 → False、a1 → False、@1 → False

    次のような関数を組んでみました。

    Private Function NewPasswordCheck(ByVal NewPass1 As String) As Boolean

      If Not System.Text.RegularExpressions.Regex.IsMatch(NewPass1, "^[0-9]+$") AndAlso
        Not System.Text.RegularExpressions.Regex.IsMatch(NewPass1, "^[A-Z]+$") Then

        MessageBox.Show("パスワードには[数字]と[英字]がそれぞれ" & vbCrLf &
                        "1文字ずつ以上含まれていなければなりません。", "入力値エラー",
                        MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
        Return False

      End If

      Return True

    End Function

    ですがこれですと、A1 → True で、希望どおりなのですが、これだけに留まらず、
    A だけの場合でも True になり、1 だけの場合でも True になってしまいます。

    これをなんとか、AND または AndAldo を使って、一発で条件に合う
    パターンマッチングにする方法はございませんでしょうか?

    それとこのパターンマッチングを改良して、上記条件 + 文字の桁が 4桁以上、8桁以下
    となるような、
    判定パターンを書くことができるようでしたら、合わせてご教示いただくことは
    できませんでしょうか。

    どうか、よろしくお願い申し上げます。

    • 編集済み kei_chan_gt 2013年8月1日 9:07 再度、書式体裁を整えました。
    2013年8月1日 8:47

回答

  • このあたり ↓ を読むときっと答えが見つかると思います。

    ASP.NET の正規表現
    http://msdn.microsoft.com/ja-jp/library/ms972966.aspx

    正規表現での量指定子
    http://msdn.microsoft.com/ja-jp/library/vstudio/3206d374.aspx

    正規表現の基本
    http://dobon.net/vb/dotnet/string/regex.html

    • 回答としてマーク kei_chan_gt 2013年8月3日 5:12
    2013年8月1日 8:57
  • こんな?

    Sub Main()
        Dim reg As New System.Text.RegularExpressions.Regex("^(?!(?!.{4,8}$))[0-9A-Z]*([0-9][A-Z]|[A-Z][0-9])+[0-9A-Z]*$")
    
        Dim ss As String() = {"A1", "1A", "AA1", "AAA", "111", "a1", "@1", "1A", "A1A", "1A1", "1a1", "@1"}
        For length As Integer = 3 To 9
            For Each s As String In ss
                Dim s2 As String
                s2 = s.PadRight(length, "1"c)
                Console.WriteLine(s2 + vbTab + reg.IsMatch(s2).ToString())
                s2 = s.PadRight(length, "A"c)
                Console.WriteLine(s2 + vbTab + reg.IsMatch(s2).ToString())
            Next
        Next
    End Sub

    2013/08/02 20:40 二重否定を使った理由の追記
    回答が酷過ぎるとレスをもらいました。「サンプルコード付きで回答した」のが酷いのか、「正しくないコード」(動作検証してあります)だから酷いのか、「コードが汚い」から酷いのか、「二重否定を使った」のが酷いのか、…(以下略)、理由が読み取れなかったので、二重否定を使った理由だけは説明。

    正規表現の先読みには「正の先読み(?=○)」と「負の先読み(?!○)」があります。
    ですが、使おうとする時に書き方を忘れることがよくあります。
    そんな時は「負の先読み」だけ覚えておけば二重否定を使うことでどちらの機能も実現できます。
    覚えておくことが半分になるなんてお得だよね?


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)




    • 編集済み gekkaMVP 2013年8月2日 11:49
    • 回答としてマーク kei_chan_gt 2013年8月3日 5:12
    2013年8月1日 9:31
  • これをなんとか、AND または AndAldo を使って、一発で条件に合うパターンマッチングにする方法はございませんでしょうか?

    たぶん正規表現そのもの問題ではないと思います。中学か高校の数学で習うはずのド・モルガンの法則とかその辺り、NotやAndAlsoを重ねたときに何がTrueになるのか、逆に欲しい条件にするにはどう組み合わせればいいのか、その辺りができていないだけだと思います。

    その上で、パターンマッチングの質問として答えるならば、上記のややこしさ、考慮漏れなどもあるため、Regex.IsMatch()を1回で完了できるようパターンを記述することをお勧めします。
    つまり、「半角大文字アルファベットと、半角数字、それぞれ一文字以上含めば True」を更に噛み砕いて理解することが重要です。
    これを「全角大文字アルファベット1文字以上の後に半角数字1文字以上、または半角数字1文字以上の後に全角大文字アルファベット1文字以上」に読み替えることができれば表現できるはずです。

    ところで小文字や記号、全角文字が含まれていた場合はどうなってほしいのでしょうか。

    • 回答としてマーク kei_chan_gt 2013年8月3日 5:12
    2013年8月1日 9:36
  • Private Function NewPasswordCheck(ByVal NewPass1 As String) As Boolean
        If NewPass1.Length < 4 OrElse NewPass1.Length > 8 Then
            MessageBox.Show("パスワードは4桁以上8桁以下で入力して下さい。" _
                , "入力値エラー", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
            Return False
        End If
        If System.Text.RegularExpressions.Regex.IsMatch(NewPass1, "^[0-9]+$") AndAlso _
           System.Text.RegularExpressions.Regex.IsMatch(NewPass1, "^[A-Z]+$") Then
            Return True
        Else
            MessageBox.Show("パスワードには[数字]と[英字]がそれぞれ" & vbCrLf & "1文字ずつ以上含まれていなければなりません。" _
                , "入力値エラー", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
            Return False
        End If
    End Function
    元々の造りを踏襲して、こんな感じでも良い気がします。
    • 回答としてマーク kei_chan_gt 2013年8月3日 5:12
    2013年8月1日 9:41
  • いくらなんでもその正規表現は…二重否定入ってますし。好き放題書いていいのなら

    "^(?:(?<upper>[A-Z])|(?<number>[0-9])|.){4,8}$(?(upper)|(?!))(?(number)|(?!))"

    とか書けますけど、回答として提示するには酷過ぎると思います。

    ところでサンプルに a1 や @1 があるということは、 aA1 や @A1 はTrueになるべきなのかな?

    • 回答としてマーク kei_chan_gt 2013年8月3日 5:12
    2013年8月1日 12:56
  • コードを書いている回答者の方がおられますが、自分の意図する方向とちょっと違うようなので、自分のお勧めを具体的に書いておきます。

    先のレスで紹介した「ASP.NET の正規表現」のページの「高度なトピック」のセクションに書いてある "ルックアラウンド処理" を利用するのが便利だと思います。

    今回の問題では以下のような感じになると思います。

    Regex regex = new Regex(@"
        ^               # 開始のアンカー
        (?=.*\d)        # 数字が 1 文字必要
        (?=.*[A-Z])     # 大文字が 1 文字必要
        [A-Z0-9]{2,}    # 大文字、数字 2 文字以上の長さ
        $               # 終了のアンカー",
        RegexOptions.IgnorePatternWhitespace);
    
    string[] testStrings = { "A1", "AA11", "AAA", "111", "a1", "@1", "あ1", "ABC123DEF", "1", "A 2B3", "" };
    
    foreach (string s in testStrings)
    {
        if (regex.IsMatch(s))
        {
            Console.WriteLine(s + "=true");
        }
        else
        {
            Console.WriteLine(s + "=false");
        }
    }

    結果は以下のようになるはずです。

    A1=true
    AA11=true
    AAA=false
    111=false
    a1=false
    @1=false
    あ1=false
    ABC123DEF=true
    1=false
    A 2B3=false
    =false

    上のコードは C# ですが、読めなければ以下のサイトで VB.NET に変換できます。

    Convert C# to VB.NET
    http://www.developerfusion.com/tools/convert/csharp-to-vb/

    • 回答としてマーク kei_chan_gt 2013年8月3日 5:12
    2013年8月1日 13:40
  • みなさん、親切丁寧なご返信をいただき深く感謝申し上げます。

    わたしの書き方が悪く、混乱させてしまいました。
    申し訳ございません。

    パスワードを登録してもらうツールを作成しておりまして、
    そのルールが、

    ・大文字のアルファベットと、数字のみで構成されること。
    ・アルファベット、数字とも最低1文字以上は入ること。
    ・4文字以上、8文字以内で構成されること。

    です。テキストボックスに入力された値をチェックする
    Functionプログラムを組みたいと思った次第です。

    投稿メッセージ中の「出したい答え」はあくまで例として
    記述いたしました。

    文面が未熟で申し訳ございませんでした。
    どうかよろしくお願い申し上げます。

    • 回答としてマーク kei_chan_gt 2013年8月3日 5:13
    2013年8月2日 1:57
  • >>佐祐理 さま

    ご返信ありがとうございます。

    いえ、a (小文字) や、@ (記号) は入ってはいけません。
    あくまで大文字のアルファベットと、数字のみです。
    しかも英字と数字がそれぞれ1文字以上入っていないといけません。

    わたしの質問が悪いせいで、ご提示いただいたチェックパターンですと
    例えば、AAAAa1 でも、True になってしまうようです。


    2013年8月2日 2:12
  • >>aviator__ さま

    ご返信ありがとうございます。

    ご提示いただいたチェックパターンですと、
    「AAA1」も、「AAAA」も、「1111」も、すべてFalse になってしまいました。

    「AAA1」のみTrue にしたいです。
    私もAviator さんのチェックパターンでいいのかと思っていましたが
    何がいけなかったのでしょうか?


    2013年8月2日 2:18
  • >>佐祐理 さま

    ご返信ありがとうございます。

    すみません。数学嫌いでした。
    勉強不足ですね。


    2013年8月2日 2:19
  • >>SurferOnWww さま

    ご返信ありがとうございます。

    ありがとうございます。
    がんばって勉強します。

    リンクをご提示いただきありがとうございます。


    2013年8月2日 2:32
  • どれが誰に対するレスなのか分からないです。

    私の先のレスのサンプルは、スレッドの表題どおり「半角大文字アルファベットと、半角数字、それぞれ一文字以上含めば True」の条件で、後出しの「4文字以上、8文字以内で構成されること。」の条件と合いませんが、2文字で修正できるはずです。



    • 編集済み SurferOnWww 2013年8月2日 4:44 一部追記
    • 回答としてマーク kei_chan_gt 2013年8月3日 5:13
    2013年8月2日 2:42
  • SurferOnWww さま

    あら?返信の時はそれぞれのご回答の下についたと思ったのに。
    大変に失礼をいたしました。すぐ修正いたします。

    2文字でですか?本当ですか??
    もう一回見直してみます。

    • 回答としてマーク kei_chan_gt 2013年8月3日 5:13
    2013年8月2日 9:29
  • > 2文字でですか?本当ですか??

    そういう言い方は避けた方がいいと思います。

    ウソは言いません。先に紹介した「ASP.NET の正規表現」に目を通してください。

    ここは Q&A サイトでなくフォーラムで、技術者同士の情報交換の場所だと自分は思っています。なので、コピペして動くようなコードを回答として求めておられるなら、自分はご期待にお応えできないかもしれません。

    • 回答としてマーク kei_chan_gt 2013年8月3日 5:13
    2013年8月2日 10:01
  • SurferOnWww さま

    すみません。からかったつもりもバカにしたつもりもありません。
    ましてや疑ったつもりでもございません。
    ご気分を害されましたらお詫び申し上げます。

    2文字で直るとご教示を受けましたので、悩みまくっていた問題が
    あと少しで解決できるのだと、うれしくてお聞き直しをしてしまった
    次第です。文字だと感情がうまく伝えられませんね。
    申し訳ございませんでした。がんばって勉強します。

    • 回答としてマーク kei_chan_gt 2013年8月3日 5:13
    2013年8月2日 10:12
  • gekka さま

    おかげさまで、gekka さまよりご教示いただいたパターンマッチングで
    行いたい処理を実現することができました。

    大変に感謝申し上げます。

    また、補足でご記載いただいた二重否定の理由も大変に勉強になりました。
    これからご教示いただいたパターンの解析を行い、勉強したいと思います。
    本当にどうもありがとうございました。

    • 回答としてマーク kei_chan_gt 2013年8月3日 5:12
    2013年8月3日 5:12

すべての返信

  • このあたり ↓ を読むときっと答えが見つかると思います。

    ASP.NET の正規表現
    http://msdn.microsoft.com/ja-jp/library/ms972966.aspx

    正規表現での量指定子
    http://msdn.microsoft.com/ja-jp/library/vstudio/3206d374.aspx

    正規表現の基本
    http://dobon.net/vb/dotnet/string/regex.html

    • 回答としてマーク kei_chan_gt 2013年8月3日 5:12
    2013年8月1日 8:57
  • こんな?

    Sub Main()
        Dim reg As New System.Text.RegularExpressions.Regex("^(?!(?!.{4,8}$))[0-9A-Z]*([0-9][A-Z]|[A-Z][0-9])+[0-9A-Z]*$")
    
        Dim ss As String() = {"A1", "1A", "AA1", "AAA", "111", "a1", "@1", "1A", "A1A", "1A1", "1a1", "@1"}
        For length As Integer = 3 To 9
            For Each s As String In ss
                Dim s2 As String
                s2 = s.PadRight(length, "1"c)
                Console.WriteLine(s2 + vbTab + reg.IsMatch(s2).ToString())
                s2 = s.PadRight(length, "A"c)
                Console.WriteLine(s2 + vbTab + reg.IsMatch(s2).ToString())
            Next
        Next
    End Sub

    2013/08/02 20:40 二重否定を使った理由の追記
    回答が酷過ぎるとレスをもらいました。「サンプルコード付きで回答した」のが酷いのか、「正しくないコード」(動作検証してあります)だから酷いのか、「コードが汚い」から酷いのか、「二重否定を使った」のが酷いのか、…(以下略)、理由が読み取れなかったので、二重否定を使った理由だけは説明。

    正規表現の先読みには「正の先読み(?=○)」と「負の先読み(?!○)」があります。
    ですが、使おうとする時に書き方を忘れることがよくあります。
    そんな時は「負の先読み」だけ覚えておけば二重否定を使うことでどちらの機能も実現できます。
    覚えておくことが半分になるなんてお得だよね?


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)




    • 編集済み gekkaMVP 2013年8月2日 11:49
    • 回答としてマーク kei_chan_gt 2013年8月3日 5:12
    2013年8月1日 9:31
  • これをなんとか、AND または AndAldo を使って、一発で条件に合うパターンマッチングにする方法はございませんでしょうか?

    たぶん正規表現そのもの問題ではないと思います。中学か高校の数学で習うはずのド・モルガンの法則とかその辺り、NotやAndAlsoを重ねたときに何がTrueになるのか、逆に欲しい条件にするにはどう組み合わせればいいのか、その辺りができていないだけだと思います。

    その上で、パターンマッチングの質問として答えるならば、上記のややこしさ、考慮漏れなどもあるため、Regex.IsMatch()を1回で完了できるようパターンを記述することをお勧めします。
    つまり、「半角大文字アルファベットと、半角数字、それぞれ一文字以上含めば True」を更に噛み砕いて理解することが重要です。
    これを「全角大文字アルファベット1文字以上の後に半角数字1文字以上、または半角数字1文字以上の後に全角大文字アルファベット1文字以上」に読み替えることができれば表現できるはずです。

    ところで小文字や記号、全角文字が含まれていた場合はどうなってほしいのでしょうか。

    • 回答としてマーク kei_chan_gt 2013年8月3日 5:12
    2013年8月1日 9:36
  • Private Function NewPasswordCheck(ByVal NewPass1 As String) As Boolean
        If NewPass1.Length < 4 OrElse NewPass1.Length > 8 Then
            MessageBox.Show("パスワードは4桁以上8桁以下で入力して下さい。" _
                , "入力値エラー", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
            Return False
        End If
        If System.Text.RegularExpressions.Regex.IsMatch(NewPass1, "^[0-9]+$") AndAlso _
           System.Text.RegularExpressions.Regex.IsMatch(NewPass1, "^[A-Z]+$") Then
            Return True
        Else
            MessageBox.Show("パスワードには[数字]と[英字]がそれぞれ" & vbCrLf & "1文字ずつ以上含まれていなければなりません。" _
                , "入力値エラー", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
            Return False
        End If
    End Function
    元々の造りを踏襲して、こんな感じでも良い気がします。
    • 回答としてマーク kei_chan_gt 2013年8月3日 5:12
    2013年8月1日 9:41
  • いくらなんでもその正規表現は…二重否定入ってますし。好き放題書いていいのなら

    "^(?:(?<upper>[A-Z])|(?<number>[0-9])|.){4,8}$(?(upper)|(?!))(?(number)|(?!))"

    とか書けますけど、回答として提示するには酷過ぎると思います。

    ところでサンプルに a1 や @1 があるということは、 aA1 や @A1 はTrueになるべきなのかな?

    • 回答としてマーク kei_chan_gt 2013年8月3日 5:12
    2013年8月1日 12:56
  • コードを書いている回答者の方がおられますが、自分の意図する方向とちょっと違うようなので、自分のお勧めを具体的に書いておきます。

    先のレスで紹介した「ASP.NET の正規表現」のページの「高度なトピック」のセクションに書いてある "ルックアラウンド処理" を利用するのが便利だと思います。

    今回の問題では以下のような感じになると思います。

    Regex regex = new Regex(@"
        ^               # 開始のアンカー
        (?=.*\d)        # 数字が 1 文字必要
        (?=.*[A-Z])     # 大文字が 1 文字必要
        [A-Z0-9]{2,}    # 大文字、数字 2 文字以上の長さ
        $               # 終了のアンカー",
        RegexOptions.IgnorePatternWhitespace);
    
    string[] testStrings = { "A1", "AA11", "AAA", "111", "a1", "@1", "あ1", "ABC123DEF", "1", "A 2B3", "" };
    
    foreach (string s in testStrings)
    {
        if (regex.IsMatch(s))
        {
            Console.WriteLine(s + "=true");
        }
        else
        {
            Console.WriteLine(s + "=false");
        }
    }

    結果は以下のようになるはずです。

    A1=true
    AA11=true
    AAA=false
    111=false
    a1=false
    @1=false
    あ1=false
    ABC123DEF=true
    1=false
    A 2B3=false
    =false

    上のコードは C# ですが、読めなければ以下のサイトで VB.NET に変換できます。

    Convert C# to VB.NET
    http://www.developerfusion.com/tools/convert/csharp-to-vb/

    • 回答としてマーク kei_chan_gt 2013年8月3日 5:12
    2013年8月1日 13:40
  • みなさん、親切丁寧なご返信をいただき深く感謝申し上げます。

    わたしの書き方が悪く、混乱させてしまいました。
    申し訳ございません。

    パスワードを登録してもらうツールを作成しておりまして、
    そのルールが、

    ・大文字のアルファベットと、数字のみで構成されること。
    ・アルファベット、数字とも最低1文字以上は入ること。
    ・4文字以上、8文字以内で構成されること。

    です。テキストボックスに入力された値をチェックする
    Functionプログラムを組みたいと思った次第です。

    投稿メッセージ中の「出したい答え」はあくまで例として
    記述いたしました。

    文面が未熟で申し訳ございませんでした。
    どうかよろしくお願い申し上げます。

    • 回答としてマーク kei_chan_gt 2013年8月3日 5:13
    2013年8月2日 1:57
  • >>佐祐理 さま

    ご返信ありがとうございます。

    いえ、a (小文字) や、@ (記号) は入ってはいけません。
    あくまで大文字のアルファベットと、数字のみです。
    しかも英字と数字がそれぞれ1文字以上入っていないといけません。

    わたしの質問が悪いせいで、ご提示いただいたチェックパターンですと
    例えば、AAAAa1 でも、True になってしまうようです。


    2013年8月2日 2:12
  • >>aviator__ さま

    ご返信ありがとうございます。

    ご提示いただいたチェックパターンですと、
    「AAA1」も、「AAAA」も、「1111」も、すべてFalse になってしまいました。

    「AAA1」のみTrue にしたいです。
    私もAviator さんのチェックパターンでいいのかと思っていましたが
    何がいけなかったのでしょうか?


    2013年8月2日 2:18
  • >>佐祐理 さま

    ご返信ありがとうございます。

    すみません。数学嫌いでした。
    勉強不足ですね。


    2013年8月2日 2:19
  • >>SurferOnWww さま

    ご返信ありがとうございます。

    ありがとうございます。
    がんばって勉強します。

    リンクをご提示いただきありがとうございます。


    2013年8月2日 2:32
  • どれが誰に対するレスなのか分からないです。

    私の先のレスのサンプルは、スレッドの表題どおり「半角大文字アルファベットと、半角数字、それぞれ一文字以上含めば True」の条件で、後出しの「4文字以上、8文字以内で構成されること。」の条件と合いませんが、2文字で修正できるはずです。



    • 編集済み SurferOnWww 2013年8月2日 4:44 一部追記
    • 回答としてマーク kei_chan_gt 2013年8月3日 5:13
    2013年8月2日 2:42
  • SurferOnWww さま

    あら?返信の時はそれぞれのご回答の下についたと思ったのに。
    大変に失礼をいたしました。すぐ修正いたします。

    2文字でですか?本当ですか??
    もう一回見直してみます。

    • 回答としてマーク kei_chan_gt 2013年8月3日 5:13
    2013年8月2日 9:29
  • > 2文字でですか?本当ですか??

    そういう言い方は避けた方がいいと思います。

    ウソは言いません。先に紹介した「ASP.NET の正規表現」に目を通してください。

    ここは Q&A サイトでなくフォーラムで、技術者同士の情報交換の場所だと自分は思っています。なので、コピペして動くようなコードを回答として求めておられるなら、自分はご期待にお応えできないかもしれません。

    • 回答としてマーク kei_chan_gt 2013年8月3日 5:13
    2013年8月2日 10:01
  • SurferOnWww さま

    すみません。からかったつもりもバカにしたつもりもありません。
    ましてや疑ったつもりでもございません。
    ご気分を害されましたらお詫び申し上げます。

    2文字で直るとご教示を受けましたので、悩みまくっていた問題が
    あと少しで解決できるのだと、うれしくてお聞き直しをしてしまった
    次第です。文字だと感情がうまく伝えられませんね。
    申し訳ございませんでした。がんばって勉強します。

    • 回答としてマーク kei_chan_gt 2013年8月3日 5:13
    2013年8月2日 10:12
  • gekka さま

    おかげさまで、gekka さまよりご教示いただいたパターンマッチングで
    行いたい処理を実現することができました。

    大変に感謝申し上げます。

    また、補足でご記載いただいた二重否定の理由も大変に勉強になりました。
    これからご教示いただいたパターンの解析を行い、勉強したいと思います。
    本当にどうもありがとうございました。

    • 回答としてマーク kei_chan_gt 2013年8月3日 5:12
    2013年8月3日 5:12
  • 正規表現の先読みには「正の先読み(?=○)」と「負の先読み(?!○)」があります。
    ですが、使おうとする時に書き方を忘れることがよくあります。
    そんな時は「負の先読み」だけ覚えておけば二重否定を使うことでどちらの機能も実現できます。
    覚えておくことが半分になるなんてお得だよね?
    その論理で言うなら * や + なんか使わずに {0,} や {1,} と書けばいいですはずですがそうはしていません。また他人の書いたコードに (?=) や (?<=) 、 (?<!) が織り交ぜられていたらどうするのでしょう。結局、gekkaさんの至極個人的なコーディングルールであり、(初出時)他人に説明なしに勧められるものではないと思います。
    2013年8月3日 7:18
  • > 覚えておくことが半分になるなんてお得だよね?

    そういわれると反論したくなるのですが、負の先読みを使うより、自分がサンプルに書いた正の先読みを使ったほうが可読性が高いと思うのですが。

    どうしても負の先読みを使うのであれば、以下のようにしたほうがよさそうです。

    Regex regex2 = new Regex(@"
        (?!^[0-9]*$)    # 数字だけではない
        (?!^[A-Z]*$)    # 大文字だけではない
        ^               # 開始のアンカー
        ([A-Z0-9]{4,8}) # 大文字または数字が 4 - 8 文字
        $               # 終了のアンカー",
        RegexOptions.IgnorePatternWhitespace);

    2013年8月3日 8:06
  • 流れに乗って私の書いた正規表現も説明しておきます。

    ^                               # 開始のアンカー
    (?:
      (?<upper>[A-Z])      # 大文字があればupperとして記憶
      |
      (?<number>[0-9])   # 数字があればnumberとして記憶
      |
      .                              # その他任意の文字。<<どうやらこれは余分だった模様>>
    ) {4,8}                      # 以上の条件の文字が4文字から8文字繰り返される
    $                               # 終了のアンカー
    (?(upper)             # ところでupperがあったかどうか
                                # あれば何もしない
     |
       (?!)                    # なければ失敗とする
    )
    (?(number)           # 同じくnumberがあったかどうか
                                 # あれば何もしない
     |
      (?!)                      # なければ失敗とする
    )

    一見複雑だけど、一番素直な実装だとは思っています。

    2013年8月3日 9:25