Search code examples
c#regexurlannotationsslug

Merging 3 Regular Expressions to make a Slug/URL validation check


I am trying to merge a few working RegEx patterns together (AND them). I don't think I am doing this properly, further, the first RegEx might be getting in the way of the next two.

Slug example (no special characters except for - and _):

(^[a-z0-9-_]+$)

Then I would like to ensure the first character is NOT - or _:

(^[^-_])

Then I would like to ensure the last character is NOT - or _:

([^-_]$)

Match (good Alias):

  • my-new_page
  • pagename

Not-Match (bad Alias)

  • -my-new-page
  • my-new-page_
  • !@#$%^&*()

If this RegExp can be simplified and I am more than happy to use it. I am trying to create validation on a page URL that the user can provide, I am looking for the user to:

  • Not start or and with a special character
  • Start and end with a number or letter
  • middle (not start and end) can include - and _

One I get that working, I can tweak if for other characters as needed.

In the end I am applying as an Annotation to my model like so:

[RegularExpression(
    @"(^[a-z0-9-_]+$)?(^[^-_])?([^-_]$)", 
    ErrorMessage = "Alias is not valid")
]

Thank you, and let me know if I should provide more information.


Solution

  • See regex in use here

    ^[a-z\d](?:[a-z\d_-]*[a-z\d])?$
    
    • ^ Assert position at the start of the line
    • [a-z\d] Match any lowercase ASCII letter or digit
    • (?:[a-z\d_-]*[a-z\d])? Optionally match the following
      • [a-z\d_-]* Match any character in the set any number of times
      • [a-z\d] Match any lowercase ASCII letter or digit
    • $ Assert position at the end of the line

    See code in use here

    using System; using System.Text.RegularExpressions;

    public class Example
    {
        public static void Main()
        {
            Regex regex = new Regex(@"^[a-z\d](?:[a-z\d_-]*[a-z\d])?$");
            string[] strings = {"my-new_page", "pagename", "-my-new-page", "my-new-page_", "!@#$%^&*()"};
    
            foreach(string s in strings) {
                    if (regex.IsMatch(s))
                    {
                        Console.WriteLine(s);
                    }
            }
        }
    }
    

    Result (only positive matches):

    my-new_page
    pagename