Regex expression to check if first and last char of set are different

Viewed 209

Say I have a string of only a's and b's, like so:

aaabbbbababab

How can I construct a regex, that will match the given string only if the second and last character are different?

This is my current attempt, that does the exact opposite (e.g. matches if second and last character are the same):

^[ab]([ab])[ab]*\1$

I am using the ECMAScript implementation of regex.

3 Answers

You can use a capture group for the second char, and only match the last char if it is not the same as capture group 1.

^[ab]([ab])[ab]*(?!\1)[ab]$
  • ^ Start of string
  • [ab] Match a or b (Note that you can omit | as it means a pipe char in the character class
  • ([ab]) Capture group 1, match either a or b
  • [ab]* Optionally match a or b
  • (?!\1) Negative lookahead, assert not the same value as captured in group 1 using the backreference \1
  • [ab]$ match either a or b at the end of the string

Regex demo

Another option is immediately do the assertion after the capture group

^[ab]([ab])(?![ab]*\1$)[ab]*$

Regex demo

Or if supported, as negative lookbehind might also work. This page shows the compatibility for Javascript and lookbehinds

^[ab]([ab])[ab]*[ab]$(?<!\1)

Regex demo

If you don't have to validate that the entire string is a bunch of abs then I would go for something universal like:

^.(.).*(?!\1).$
  • ^. - start with one char
  • (.) - put the second char in a capture group
  • .* - optionally capture everything moving forward
  • (?!\1).$ - ensure the final char is not the same as the second

https://regex101.com/r/k47PUu/1/

Just for alternatives sake you could try:

^[ab]{3,}(?<!^.\1.*(.))$

See an online demo.

  • ^ - Start line anchor.
  • [ab]{3,} - 3+ Times literally "a" or "b".
  • (?<!^.\1.*(.) - Negative lookbehind to assert that last character is not the same as the 2nd.
  • $ - End line anchor.

Or, you could try a negative lookahead (which strangely is the most efficient while testing):

^(?!.(.).*\1$)[ab]{3,}$

See an online demo.

  • ^ - Start line anchor.
  • (?!.(.).*\1$) - Negative lookahead to assert 2nd character is not the same as the very last one before the end line anchor.
  • [ab]{3,} - 3+ Times literally "a" or "b".
  • $ - End line anchor.
Related