Q:

c# regex match: length 5-24 with at most 1 underscore

I want to regex match a string that

Is alphanumeric only.
Letters may only be uppercase.
Total length of min 5 and max 24 chars.
May include min 0 max 1 occurrences of underscore in any position except the first or last.

I think I have to somehow nest the statements so that the total length is 5-24 but there may be up to one underscore. I have read a few regex tutorials , but can't understand a way to do this. Also have NO idea how to specify the acceptable position of the underscore (if present).
[A-Z0-9]{5,24}[_]{0,1}

A:

If you are using this in C# code, it's better to check the length of the string outside the regex. (It's possible to cram it inside the regex, but I won't show it here).
private static bool Validate(string str) {
    if (str.Length < 5 || str.Length > 24) {
        return false;
    }

    return Regex.IsMatch(str, @"^[A-Z0-9]+(?:_[A-Z0-9]+)?\z");
}

The regex is:
^[A-Z0-9]+(?:_[A-Z0-9]+)?\z

If a string ends with new line, $ can match the empty string before new line, so \z is used here to assert end of string.
Test code
using System;
using System.Text.RegularExpressions;

public class Test
{
    public static void Main()
    {
        string[] fail = {"ABCDacbd", "ACDE", "ABCDE\n", "_01234", "ABCDÉ", "ABCD́Ē", "ABCDEF_", "A_B_CDEF", "AB_C", "1234567890123456789012345", "123456_789012345678901234"};
        string[] ok = {"ACBDEF", "01234", "ABC_DE1", "123456789012345678901234", "12345_789012345678901234"};

        foreach (string s in fail) {
            Console.WriteLine(s + " " + Validate(s));
        }
        Console.WriteLine();

        foreach (string s in ok) {
            Console.WriteLine(s + " " + Validate(s));
        }
    }

    private static bool Validate(string str) {
        if (str.Length < 5 || str.Length > 24) {
            return false;
        }

        return Regex.IsMatch(str, @"^[A-Z0-9]+(?:_[A-Z0-9]+)?\z");
    }
}

