1

I have already found helpful answers for a regex that matches twitter like username mentions in this answer and this answer

(?<=^|(?<=[^a-zA-Z0-9-_\.]))@([A-Za-z]+[A-Za-z0-9_]+)

(?<=^|(?<=[^a-zA-Z0-9-_\.]))@([A-Za-z]+[A-Za-z0-9-_]+)

However, I need to update this regex to also include usernames that has dots.

  • One or more dots are allowed in a username.
  • The username must not start or end with a dot.
  • No two consecutive dots are allowed.

Example of a matched string:

@valid.user.name
^^^^^^^^^^^^^^^^

Examples of non-matched strings:

@.user.name // starts with a dot
@user.name. // ends with a dot
@user..name // has two consecutive dots
Saleh Rezq
  • 193
  • 1
  • 13

3 Answers3

2

You can use this refactored regex:

(?<=[^\w.-]|^)@([A-Za-z]+(?:\.\w+)*)$

RegEx Demo

RegEx Details:

  • (?<=[^\w.-]|^): Lookbehind to assert that we have start of line or any non-word, non-dot, non-hyphen character before current position
  • @: Match literal `@1
  • (: Start capture group
    • [A-Za-z]+: Match 1+ ASCII letters
    • (?:\.\w+)*: Match 0 or more instances of dot followed 1+ word characters
  • ): End capture group
  • $: End
anubhava
  • 761,203
  • 64
  • 569
  • 643
1

The (?<=^|(?<=[^a-zA-Z0-9-_\.])) is a positive lookbehind that requires a match to be at the start of the string or right after an alphanumeric, -, _, ., you may write it in a more compact way as (?<![\w.-]), a negative lookbehind.

Next, ([A-Za-z]+[A-Za-z0-9_]+) captures 1+ ASCII letters and then 1+ ASCII letters or/and underscores. You seem to make sure the first char is a letter, then any number of sequences of . and 1+ word chars are allowed, that is, you may use [A-Za-z]\w*(?:\.\w+)*.

As you do not want to match it if there is a . right after the expected match, you need to set a lookahead that will require a space or end of string, (?!\S).

So, combining it, you can use

'~(?<![\w.-])@([A-Za-z]\w*(?:\.\w+)*)(?!\S)~'

See the regex demo

Details

  • (?<![\w.-]) - no letters, digits, _, . and - immediately to the left of the current location are allowed
  • @ - a @ char
  • ([A-Za-z]\w*(?:\.\w+)*) - Group 1:
    • [A-Za-z] - an ASCII letter
    • \w* - 0+ letters, digits, _
    • (?:\.\w+)* - 0+ sequences of
      • \. - dot
      • \w+ - 1+ letters, digits, _
  • (?!\S) - whitespace or end of string are required immediately to the right of the current location.
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
1

EDIT: Simpler version (same result)

^@[a-zA-Z](\.?[\w-]+)*$

Original

Another one:

^@[a-zA-Z][a-zA-Z_-]?(\.?[\w\d-]+){0,}$

  • ^@ starts with @
  • [a-zA-Z] first char
  • [a-zA-Z_-]? match a-zA-Z_- 0 or more times
  • ( start group
    • \.? match . (optional)
    • [\w\d-]+ match a-zA-Z0-9-_ 1 or more times
  • ) end group
  • {0,} repeat group 0 to infinite times
  • $ end

Tests

valid:

@validusername
@valid.user.name
@valid-user-name
@valid_user-name
@valid-user123_name
@a.valid-user123_name

not valid:

@-invalid.user
@_invalid.user
@1notvalid-user_123name33
@.user.name
@user.name.
@user..name
SirPilan
  • 4,649
  • 2
  • 13
  • 26