Regular Expression for not allowing two consecutive special characters and also not in beginning and end

Viewed 867

I'm looking for a regex for a string to

  1. Contain only A-Z a-z 0-9 _ - .
  2. Not begin/end with _ - .
  3. Not containing consecutive special characters or their combination
  4. Max 36 length, minimum 1

Right

abcd-efgH
1
a
123
abc
abc-asd-123-asd_asd.asd

Wrong:

-
abc-_asd
abc.
abc.-asd
123123-123123-ads--asd
091-asdsad---

I seearched around and got this :-

/^(?!.*[^\na-z0-9]{2})(?=.*[a-z0-9]$)[a-z0-9].*$/gim

but this allows all special characters and not just the 3 that i checek

3 Answers

You may use this regex with 3 lookaheads:

^(?![-_.])(?!.*[-_.]{2})(?!.*[-_.]$)[-\w.]{1,36}$

RegEx Demo

RegEx Details:

  • ^: Start
  • (?![-_.]): Negative lookahead to disallow [-_.] at the start
  • (?!.*[-_.]{2}): Negative lookahead to disallow 2 consecutive [-_.] anywhere
  • (?!.*[-_.]$): Negative lookahead to disallow [-_.] at the end
  • [-\w.]{1,36}: Match a [-a-zA-Z0-9_.] character, min: 1, max: 36
  • $: End

Do you mean something like:

/^(?!.{37,})[a-z\d]+(?:[-._][a-z\d]+)*$/gim

See the online demo


  • ^ - Start string ancor.
  • (?!.{37,}) - Negative lookahead for 37 characters or more.
  • [a-z\d]+ - At least a single character within this character group.
  • (?: - Open non-capturing group.
    • [-._] - A single character within this character group.
    • [a-z\d]+ - At least a single character within this character group.
    • )* - Close non-capturing group and match it zero or more times.
  • $ - End string ancor.

I think the simplest and most direct way to solve this problem, in an intuitive and logical way, is the following:

/^([a-z\d]|(?<![-_])(?<!^)[-_](?!$)){2,36}$/gim

The explanation is pretty simple.

The first char can be letter or digit OR (|) the first character can be additionally be _ or -, since the previous char

a) is not _ neither -.

The previous char condition is in the negative lookbehind: (?<![-_])

It means, using the current cursor position, a negative look behind (represented by (?<! P) model, where P is a pattern) and it's ok just if pattern P don't (negative) fit (PS: Lookbehind don't move the cursor) In this case, pattern P is just [-_]. If P behind is not - neither _, it means that - or _ are allowed as a option!

b) _ ou - is not in the start

Right after that we have another negative look behind that tests only the beginning of the text. P is just ^(the anchor that indicates start of the text). The look behind piece is (?<!^) (P is just ^)

c) _ ou - is not in the end

Finally we have a negative look forward, but is appears after [-_] real pattern. The only syntax difference is cut "<" character (?!P, where P is the pattern). Now, the regex processing is search forward for the pattern P, without move the cursor. If the pattern fail is OK (negative!) In the case, we have (?!$), where P is $, the anchor that indicates the end of the text.

for example: ABCDEFGHIJKLMNOPQRSTU-XYZ01234_56789 matches but ABCDEFGHIJKLMNOPQRSTU-_XYZ0123456789 doesn't match neither ABCDEFGHIJKLMNOPQRSTU-XYZ012345678_ neither _BCDEFGHIJKLMNOPQRSTU-XYZ0123456789

See online here:

Related