-2

I need a regular expression for a URL-friendly slug, which can only contain lowercase letters and hyphens. It can't start or end with a hyphen and can't have more than one consecutive dash.

It will be used in a data annotation in C#:

[RegularExpression("", ErrorMessage = "Slug can only contain lowercase letters and dash; must not start or end with a dash; must not have more then 1 consecutive dash.")] 

I tried the following expressions from this question.

/^[a-z0-9]+(?:-[a-z0-9]+)*$/ /^[a-z0-9]+(?:[_-][a-z0-9]+)*$/ 
  1. How can I modify the expressions to validate what I need?
  2. Can someone further explain how the non-capture group works in this case? I didn't understand the explanation I got from Google.

c-sharp (valid) c-sharp-code (valid) -csharp (invalid) csharp- (invalid) c--sharp (invalid) csharp9 (invalid) c_sharp (invalid)

6
  • The non-capturing groups are because you need a group to attach a quantifier (+) too, but without the cost of it being a normal capturing group. Commented Nov 7, 2023 at 16:49
  • ...but for your needs, you don't need any noncapturing-groups (or any groups at all). Commented Nov 7, 2023 at 16:50
  • Protip: use Regex101.com for help with regular-expressions. Commented Nov 7, 2023 at 16:51
  • I think you mean like this without matching digits right? ^[a-z]+(?:-[a-z]+)*$ regex101.com/r/a05kLh/1 Commented Nov 7, 2023 at 16:58
  • @Dai I can't get it to work without that non-capturing group. If I remove it, it no longer seems to check for consecutive hyphens. Commented Nov 7, 2023 at 16:59

2 Answers 2

0

This expression also answers the question:

^[a-z]+(?:-[a-z]+)*$ 

It meets all the requirements I originally needed.

Sign up to request clarification or add additional context in comments.

Comments

-1

Use:

^[a-z](?!.*--)[a-z\-]*[a-z]$ 

Demo: https://regex101.com/r/qXNO3y/3

Explanation:

^ # Anchor at start of string. [a-z] # The first character must be in the range [a-z]. (?!.*--) # Assert that "--" does not appear anywhere from this point onwards. [a-z\-]* # Allow any subsequent chars to be in the range [a-z], or be '-' (while never matching "--" due to the assertion prior). [a-z] # The last character must be in the range [a-z] $ # Anchor to the end of the string. 

Usage:

static readonly Regex _slugRegex = new Regex( @"^[a-z](?!.*--)[a-z\-]*[a-z]$", RegexOptions.Compiled ); _slugRegex.IsMatch( "foo-bar" ); // OK _slugRegex.IsMatch( "foo--bar" ); // Fails _slugRegex.IsMatch( "foo-bar-" ); // Fails _slugRegex.IsMatch( "-foo-bar" ); // Fails 

5 Comments

It doesn't seem to work, because it allows digits.
@KennethR.Jones Whoops, sorry. check now.
Almost, but it still validates "csh-a-rp-". That should fail, because there is a dash at the end.
Third-time lucky?
@KennethR.Jones What what says?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.