Regex - как проверить при наборе текста (даже если текст не полный) - PullRequest
1 голос
/ 31 марта 2020

Я хочу установить регулярное выражение для адреса электронной почты таким образом, чтобы оно проверялось во время ввода (используя JF XML):

String reg = "(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])";
Pattern pattern = Pattern.compile(reg);
System.out.println( pattern.matcher("eshaka@horm").matches());

это код, который я использовал, но это может только определять, является ли текущий текст действительным электронным письмом или нет.

  1. Не только обнаруживать, когда я набрал действительный адрес.
  2. Я хочу определить, что я набрал до сих пор в пределах адреса электронной почты, а не я от ввода недопустимого символа.

Пример:

emails is some_one@somemail.com

some_o входит в сферу действия электронного письма. но не полный адрес электронной почты. поэтому позвольте мне продолжать печатать, но не следует принимать его как электронное письмо.

some_one@some@ma этот содержит два @s, что является незаконным. Я хочу, чтобы текстовое поле не давало пользователю ввести этот @.

1 Ответ

5 голосов
/ 01 апреля 2020

Использование Matcher.hitEnd(). Этот метод предназначен именно для определения того, может ли дополнительный вклад изменить результат. Таким образом, если шаблон не совпадает и конец не достигнут, добавление большего количества символов в конец не решит проблему. Это не исключает того, что вставка в другую позицию может решить эту проблему:

static final Pattern VALID_MAIL = Pattern.compile(…);// insert actual pattern here

enum Status { VALID, INVALID, INCOMPLETE }

static Status check(CharSequence cs, boolean complete) {
  Matcher matcher = VALID_MAIL.matcher(cs);
  if(matcher.matches()) return Status.VALID;
  return complete || !matcher.hitEnd() ? Status.INVALID : Status.INCOMPLETE;
}

Для имитации набора текста:

String[] samples = { "eshaka@horm", "some_one@some@ma",
                     "some_one@somemail.com", "@domain.name" };

for(String input: samples) {
  StringBuilder typing = new StringBuilder();
  input.codePoints().forEach(cp -> {
    System.out.println(typing.appendCodePoint(cp) + ": "
        + check(typing, typing.length()==input.length()));
  });
  System.out.println();
}

При использовании шаблона, используемого в вашем вопросе, это приводит к:

e: INCOMPLETE
es: INCOMPLETE
esh: INCOMPLETE
esha: INCOMPLETE
eshak: INCOMPLETE
eshaka: INCOMPLETE
eshaka@: INCOMPLETE
eshaka@h: INCOMPLETE
eshaka@ho: INCOMPLETE
eshaka@hor: INCOMPLETE
eshaka@horm: INVALID

s: INCOMPLETE
so: INCOMPLETE
som: INCOMPLETE
some: INCOMPLETE
some_: INCOMPLETE
some_o: INCOMPLETE
some_on: INCOMPLETE
some_one: INCOMPLETE
some_one@: INCOMPLETE
some_one@s: INCOMPLETE
some_one@so: INCOMPLETE
some_one@som: INCOMPLETE
some_one@some: INCOMPLETE
some_one@some@: INVALID
some_one@some@m: INVALID
some_one@some@ma: INVALID

s: INCOMPLETE
so: INCOMPLETE
som: INCOMPLETE
some: INCOMPLETE
some_: INCOMPLETE
some_o: INCOMPLETE
some_on: INCOMPLETE
some_one: INCOMPLETE
some_one@: INCOMPLETE
some_one@s: INCOMPLETE
some_one@so: INCOMPLETE
some_one@som: INCOMPLETE
some_one@some: INCOMPLETE
some_one@somem: INCOMPLETE
some_one@somema: INCOMPLETE
some_one@somemai: INCOMPLETE
some_one@somemail: INCOMPLETE
some_one@somemail.: INCOMPLETE
some_one@somemail.c: VALID
some_one@somemail.co: VALID
some_one@somemail.com: VALID

@: INVALID
@d: INVALID
@do: INVALID
@dom: INVALID
@doma: INVALID
@domai: INVALID
@domain: INVALID
@domain.: INVALID
@domain.n: INVALID
@domain.na: INVALID
@domain.nam: INVALID
@domain.name: INVALID

Таким образом, для определенных входных данных мы можем рано определить, что ввод будет оставаться недействительным, когда вводится только вперед, тогда как другие, например eshaka@horm, могут считаться недействительными только тогда, когда мы говорим, что они должны быть завершены.

Вы также можете использовать эту функцию, чтобы найти проблему:

static void feedback(CharSequence input) {
  System.out.append(input).append(": ");
  Matcher matcher = VALID_MAIL.matcher(input);
  if(matcher.matches()) System.out.println("Ok");
  else if(matcher.hitEnd()) System.out.println("Type ahead");
  else {
    for(int p = 0; p < input.length(); p++)
      if(!matcher.region(0, p).matches() && !matcher.hitEnd()) {
        System.out.println("(First) problem at position "+p);
        break;
      }
  }
}
for(String input: samples) feedback(input);
eshaka@horm: Type ahead
some_one@some@ma: (First) problem at position 14
some_one@somemail.com: Ok
@domain.name: (First) problem at position 1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...