1

Sorry if this a duplicate, I didn't find similar question, maybe I missed something...

I will explain what I want by example:

  • Suppose we have a simple regular expression for checking email

    private static final String EMAIL_PATTERN = "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";

  • I start to enter (in some input field) email (or not email, but some string) symbol by symbol and check whole line by regex.

    • Enter: u
    • Line: u
    • Check: true \\ because there is a chance that I will enter right symbols further

    • Enter: s
    • Line: us
    • Check: true

      ...

    • Enter: @
    • Line: username@
    • Check: true

    • Enter: @
    • Line: username@@
    • Check: false \\ because there is no way to get correct line appending any symbols

    • Enter: d
    • Line: username@d
    • Check: true

    • Enter: .
    • Line: username@domain.
    • Check: true

    • Enter: .
    • Line: username@domain..
    • Check: false

By other words I want to check string by regex and get positive result if there is possibility that appending symbols will give us correct string.

Igor Tyulkanov
  • 5,487
  • 2
  • 32
  • 49
  • Maybe while typing you should think more about what's *illegal* cases and only on submit/focusLost/whatever check that it's also matching your regex? Illegal would be : more than one @, @ at the beginning, consecutive dots... – Jan Dec 10 '15 at 10:20
  • @jan this is not about checking while entering, I said it just for example – Igor Tyulkanov Dec 10 '15 at 10:42
  • If you don't plan to check while entering your example is very confusing. – Jan Dec 10 '15 at 10:48
  • Maybe, I just want to check any string by any regex and get positive result if there is possibility that appending symbols will give me correct string – Igor Tyulkanov Dec 10 '15 at 10:51

3 Answers3

2

First things first...

Your E-Mail Regex is wrong

E-Mails are extremely hard to validate just on the base of how the address looks... Most times people just do it wrong. You too. Sorry.

This is not really about regex, but about UX...

You are probably better off just allowing the user to enter whatever they want, and tell them if their email is likely to be mistyped, and not prevent the user from entering it in the first place.

As to validating while input

If you still want to run with your regex, just make the later parts optional, so the incomplete parts match the regex already.

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

/^[_a-z0-9-\+.-]+(\.[_a-z0-9-]+)*@?([a-z0-9+\-]+\.)*[a-z0-9+\-]*$/i
Community
  • 1
  • 1
F.P
  • 17,421
  • 34
  • 123
  • 189
2

What you can use here is ?. That is the symbol for making the preceding symbol optional. Your example is bad as email shouldn't be validated via regex so I'll use something else.

Suppose you want to match the following

4 alphabets then 2 digits then 4 alphabets

So you can use a regex like

(?:\w{0,4})?(?:\d{0,2})?(?:\w{0,4})?

The below is called a non-capturing group. You can use a capturing group but you shouldn't due to performance as you don't need the captured stuff.

(?: something)

Explantation

Basically what I did was go and decide what were the pieces of my string in my initial specification of

4 alphabets ..

and then I broke each piece into a separate regex and make it optional so that my regex is basically saying

  • Match 0 to 4 characters optionally and match further
  • Match 0 to 2 digits optionally and match further
  • Match 0 to 4 characters optionally and match further

The above is not full proof. It can give false positives but if the concern is whether appending may give correct result and you don't need absolutes then you can use this approach.

For better results i.e. absolutely correct results you can have lookbehinds. But be warned that can become complicated. But if you are looking for something simple this can work.

Aseem Bansal
  • 6,722
  • 13
  • 46
  • 84
0

You can use the regex.Pattern and regex.Matcher classes from the util package

import java.util.regex.Matcher;
import java.util.regex.Pattern;

//...

private static final String EMAIL_PATTERN = "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";    

// String to be scanned to find the pattern.
String line = "Your line";
String pattern = EMAIL_PATTERN;

// Create a Pattern object
Pattern r = Pattern.compile(pattern);

// Now create matcher object.
Matcher m = r.matcher(line);

// You can use capturing groups to partially check the line
// e.g. for Java 6 use the following to access the first group
String value = m.group(0);

// True, in case the matcher did not find any according value:
value.equals("NO MATCH"); 

compare http://www.tutorialspoint.com/java/java_regular_expressions.htm and Java Regex Capturing Groups

You could then check the different groups and as soon as there is a group that is not matched, but a following group does have a match, your case in which no valid input would be possible anymore (by adding only).

To make it work with your example, you can call say a validate function that implements the above code on every enter-event, e.g. a key-down event. But that depends on your UI-framework

Community
  • 1
  • 1