регулярное выражение обнаружить слово с 2+ числа и 2+ символа - PullRequest
2 голосов
/ 16 мая 2019

Мне нужно одно регулярное выражение для определения слов длиной 8 символов, которые содержат 2+ цифры и 2+ символов (без специальных символов).

Я близок к решению, и я сделал регулярное выражение на regex101.com .

Проблема в том, что слова содержат одно число, которое не должно быть подходящим для моего регулярного выражения.

Я отбросил все слова с символами, которые содержат не менее 7 символов с (?![A-Za-z]{7,}).

Я отбросил все слова с номерами, которые содержат минимум 7 чисел с (?![\d]{7,}).

И я отбросил слова, которые содержат минимум 2 цифры и 2 символа (?=[a-zA-Z\d]{2})[A-Za-z\d]{8}.

Почему vaff8loe совпадает?

Я создал это регулярное выражение, потому что после того, как я хочу заменить все слово на *******. Как:

papave23 ciao il mio pin papaver1 è reeredji332ji con vaff8loe 1234567o 123t123t papavero 9o 123t123y

После с заменой ("regex", "********")

********ciao il mio pin papaver1 è reeredji332ji con ******** 1234567o ******** papavero 9o ********

Ответы [ 3 ]

3 голосов
/ 16 мая 2019

Используйте 2 положительных просмотра нулевой ширины:

(?=.*?[a-zA-Z].*?[a-zA-Z])    Must contain 2 ASCII letters
(?=.*?[0-9].*?[0-9])          Must contain 2 digits
[a-zA-Z0-9]{8}                Must be exactly 8 letters and/or digits

Добавьте ^ и $, если не используете matches() для запуска регулярного выражения.

Это означает полное регулярное выражениеиз:

^(?=.*?[a-zA-Z].*?[a-zA-Z])(?=.*?[0-9].*?[0-9])[a-zA-Z0-9]{8}$

Для лучшей производительности замените шаблон . на класс отрицательных символов.В этом случае вы можете захотеть сократить его с помощью повторяющейся группы без захвата:

(?=(?:[^a-zA-Z]*[a-zA-Z]){2})
(?=(?:[^0-9]*[0-9]){2})

ОБНОВЛЕНИЕ

Поскольку вопрос был обновлен, чтобы сказать, что регулярное выражениенеобходимо заменить такие слова на *, якоря ^ и $ должны быть заменены на \b шаблоны границ слов, а классы отрицательных символов должны быть изменены, чтобы пропустить только допустимые символы:

s = s.replaceAll("\\b(?=(?:[0-9]*[a-zA-Z]){2})(?=(?:[a-zA-Z]*[0-9]){2})[a-zA-Z0-9]{8}\\b", "********");

См. regex101 для демонстрации.

Обратите внимание, что vaff8loe в данном примере содержит только 1 цифру, поэтому не должно заменяться.

2 голосов
/ 16 мая 2019

В ситуациях, когда вам нужно применить так много условий к вашему синтаксическому анализу (слово должно иметь длину == 8, 2+ буквенных символа, 2+ цифровых символов и никаких специальных символов), я думаю, вы должны стремиться к решениям, которые вы можете читать вместо того, чтобы бросать все внутри одного сложного регулярного выражения.

Если вы используете решение @ Andreas , ваш код будет выглядеть следующим образом:

let s = "papave23 ciao il mio pin papaver1 è reeredji332ji con vaff8loe 1234567o 123t123t papavero 9o 123t123y";

s = s.replace(/\b(?=(?:[0-9]*[a-zA-Z]){2})(?=(?:[a-zA-Z]*[0-9]){2})[a-zA-Z0-9]{8}\b/g, "********");

console.log(s);

Непонятно, что вы здесь делаете, и возможные ошибки и / или изменения в вашей логике будет трудно поддерживать.Вместо этого вы можете воспользоваться параметром замены , чтобы нарушить ваши правила.Тогда у вас будет что-то вроде этого:

let s = "papave23 ciao il mio pin papaver1 è reeredji332ji con vaff8loe 1234567o 123t123t papavero 9o 123t123y";

// The first regex filters only 8-length words
s = s.replace(/\b\w{8}\b/g, 
    function(fullMatch) {
      // .match() can return null if no match is found, 
      // so I'm accounting for this.
      const digitMatch = fullMatch.match(/\d/g) || [];
      const letterMatch = fullMatch.match(/[a-zA-Z]/g) || [];
      const specialCharMatch = fullMatch.match(/\[^a-zA-Z0-9]/g);

      if (digitMatch.length >= 2
       && letterMatch.length >= 2
       && specialCharMatch === null) {
        return "********";
       } else {
        return fullMatch;
       }
  });

console.log(s);

Это более многословно, но также более читабельно и отлаживаемо.

Надеюсь, это поможет!

2 голосов
/ 16 мая 2019

Вы можете использовать положительные шаблоны прогнозирования, чтобы ограничить количество цифр и алфавитов:

\b(?=(?:\w*\d){2}\w*)(?=(?:\w*[A-Za-z]){2}\w*)\w{8}\b

Демо: https://regex101.com/r/z33bUv/7

...