简体   繁体   中英

Progressive validation of email address via RegEx in Javascript

I'd like to do progressive validation of an email address. By that I mean I would like to validate, as a string is being provided one character at a time, whether or not the current string represents a valid beginning of an email address.

Note that I'm aware of this and other similar answers that provide excellent patterns for matching a complete email address. What I'm looking for is slightly different.

I'd like to know, given a regex pattern, say the below pattern as described in the link above, if there's a general way to say if a given string represents a valid beginning of the pattern.

 /^(([^<>()\\[\\]\\\\.,;:\\s@"]+(\\.[^<>()\\[\\]\\\\.,;:\\s@"]+)*)|(".+"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/ 

I understand that I can manually decompose the above pattern into composite sections and "OR" them together for longer pattern captures from the beginning of the main pattern forward, but I'm hoping there's something a little more elegant and/or a little less verbose that could just reference the established pattern as a capture group and look inside for a partial matches of the beginning only. Is this possible to achieve with regular expressions?

Strings the regex would match:

  • ""
  • "test"
  • "test.user"
  • "test.user."
  • "test.user.1@"
  • "test.user.1@test"
  • "test.user.1@test.best"
  • "test.user.1@test.best.com"

Strings the regex would not match:

  • "@#$@#"
  • "test.."
  • "test.user.@"
  • "test.user.1@@"
  • "test.user.1@test..best"
  • "test.user.1@test.best@"

I'm simplifying the email pattern to /^[az]+(\\.[az]+)*@[az]+(\\.[az]+)+$/ to simplify the step of the method.

  1. You identify a scenario for entering a valid value with a pattern:
Value             regex                                     matches
----------------- ----------------------------------------- ---------
t                 /^[a-z]+/                                 Yes
to                /^[a-z]+/                                 Yes
tom               /^[a-z]+/                                 Yes
tom.              /^[a-z]+\./                               Yes
tom.e             /^[a-z]+(\.[a-z]+)*/                      Yes
tom.ed            /^[a-z]+(\.[a-z]+)*/                      Yes
tom.ed@           /^[a-z]+(\.[a-z]+)*@/                     Yes
tom.ed@i          /^[a-z]+(\.[a-z]+)*@[a-z]+/               Yes
tom.ed@in         /^[a-z]+(\.[a-z]+)*@[a-z]+/               Yes
tom.ed@int        /^[a-z]+(\.[a-z]+)*@[a-z]+/               Yes
tom.ed@inte       /^[a-z]+(\.[a-z]+)*@[a-z]+/               Yes
tom.ed@inter      /^[a-z]+(\.[a-z]+)*@[a-z]+/               Yes
tom.ed@inter.     /^[a-z]+(\.[a-z]+)*@[a-z]+\./             Yes 
tom.ed@inter.n    /^[a-z]+(\.[a-z]+)*@[a-z]+(\.[a-z]+)+/    Yes
tom.ed@inter.ne   /^[a-z]+(\.[a-z]+)*@[a-z]+(\.[a-z]+)+/    Yes
tom.ed@inter.net  /^[a-z]+(\.[a-z]+)*@[a-z]+(\.[a-z]+)+$/   Yes
  1. Then you look for ways to combine a pattern that only match 1 line with the previous pattern.

    • For /^[az]+\\./ , we can combine it with /^[az]+/ and obtain /^[az]+\\.?/ .
    • For /^[az]+(\\.*[az]+)*@/ , we can combine it with /^[az]+(\\.*[az]+)*/ and obtain /^[az]+(\\.*[az]+)*@?/ .
    • For /^[az]+(\\.*[az]+)*@[az]+\\./ , we can combine it with /^[az]+(\\.*[az]+)*@[az]+/ and obtain /^[az]+(\\.*[az]+)*@[az]+\\.?/ .
    • ...

You continue until you are satisfied that you have covered all possible case.

  1. You put everything together using this /^( ... | ... | ... | ... )/ . Here a possible regex you would obtain :

/^([az]+\\.?|[az]+(\\.[az]+)*\\.?|[az]+(\\.[az]+)*@|[az]+(\\.[az]+)*@[az]+\\.?|[az]+(\\.[az]+)*@[az]+(\\.[az]+)*\\.?|[az]+(\\.[az]+)*@[az]+(\\.[az]+)+)$/

Her is a better view :

( [a-z]+\.?
| [a-z]+(\.[a-z]+)*\.?
| [a-z]+(\.[a-z]+)*@
| [a-z]+(\.[a-z]+)*@[a-z]+\.?
| [a-z]+(\.[a-z]+)*@[a-z]+(\.[a-z]+)*\.?
| [a-z]+(\.[a-z]+)*@[a-z]+(\.[a-z]+)+ )
  1. Last you test to see if it will allows unwanted values

You can do that at regex101.com or in a test page.

Note : This pattern is only good while the user enters a value. Before submitting, the original pattern ( /^[az]+(\\.[az]+)*@[az]+(\\.[az]+)+$/ ) must be used to validate the value so that no incomplete values are sent to the server.

EDIT : To make it more readable and maintainable, you can do

var patt1 = "[a-z]+\.?";
var patt2 = "[a-z]+(\.[a-z]+)*@";
var patt3 = "[a-z]+(\.[a-z]+)*@[a-z]+\.?";
var patt4 = "[a-z]+(\.[a-z]+)*@[a-z]+(\.[a-z]+)*\.?";
var patt5 = "[a-z]+(\.[a-z]+)*@[a-z]+(\.[a-z]+)+";

var keypressedValidator = new RegExp("^("+patt1+"|"+"+patt2+"|"+"+patt3+"|"+"+patt4+"|"+"+patt5+")$");

...

var inputValue = document.getElementById(...some Id...).value;

if ( ! inputValue.match(keypressedValidator)) {
  ... show error status or error message ...
...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM