Мне нужно регулярное выражение, которое проверяет строку для
A-Za-z0-9#,.-_
Есть ли способ, которым я могу обернуть это в одном регулярном выражении (в настоящее время у меня есть функция javascript и php, которая выполняет три отдельных теста, один из которых равен 14, другой – по меньшей мере два числа, а другой – не менее 6 букв.
Таким образом, было бы справедливо следующее:
Легко! Сначала давайте посмотрим на прокомментированную версию в PHP:
$re = '/# Match 14+ char password with min 2 digits and 6 letters. ^ # Anchor to start of string. (?=(?:.*?[A-Za-z]){6}) # minimum of 6 letters. (?=(?:.*?[0-9]){2}) # minimum of 2 numbers. [A-Za-z0-9#,.\-_]{14,} # Match minimum of 14 characters. $ # Anchor to end of string. /x';
Вот версия JavaScript:
var re = /^(?=(?:.*?[A-Za-z]){6})(?=(?:.*?[0-9]){2})[A-Za-z0-9#,.\-_]{14,}$/;
Добавление 20121130:
Я заметил, что этот ответ недавно получил преимущество. Это использует более устаревшее выражение, поэтому я решил, что пришло время обновить его с лучшей …
Избавляясь от точечной звезды в целом и жадно применяя более точное выражение (отрицательный класс char), получается еще более эффективное решение:
$re = '/# Match 14+ char password with min 2 digits and 6 letters. ^ # Anchor to start of string. (?=(?:[^A-Za-z]*[A-Za-z]){6}) # minimum of 6 letters. (?=(?:[^0-9]*[0-9]){2}) # minimum of 2 numbers. [A-Za-z0-9#,.\-_]{14,} # Match minimum of 14 characters. $ # Anchor to end of string. /x';
Вот новая версия JavaScript:
var re = /^(?=(?:[^A-Za-z]*[A-Za-z]){6})(?=(?:[^0-9]*[0-9]){2})[A-Za-z0-9#,.\-_]{14,}$/;
Изменить: Добавлено #,.-_
список допустимых символов.
Изменить: Изменена жадная до ленивой звезды.
Редактировать 20121130: Добавлена альтернативная версия с заменой ленивой точки-звезды более эффективным жадным применением более точного выражения.
Я бы рекомендовал несколько проверок, написав одно регулярное выражение для этого, было бы уродливо. Несколько проверок также позволяют узнать, какие критерии не были выполнены.
$input = 'blabla2bla2f54a'; $errors=array(); if (!preg_match('/^[A-Za-z0-9#,.\-_]*$/', $input)) $errors[] = 'Invalid characters'; if (strlen($input) < 14) $errors[] = 'Not long enough'; if (strlen(preg_replace('/[^0-9]/','',$input)) < 2) $errors[] = 'Not enough numbers'; if (strlen(preg_replace('/[^A-Za-z]/','',$input)) < 6) $errors[] = 'Not enough letters'; if (count($errors) > 0) //Didn't work { echo implode($errors,'<BR/>'); }
echo preg_match("/(?=.*[#,.-_])((?=.*\d{2,})(?=.*[a-zA-Z]{6,}).{14,})/", $string);
Вывод:
blabla2bla2f54a (1) thisIsNotValidAtAll (0)
Нет, это невозможно, потому что на самом деле вы хотите сделать три отдельных проверки. Вы не можете их обернуть в одном выражении, которое возвращает true или false. Проблема в том, что у вас есть две равные проверки, которые вам нужно будет комбинировать с помощью оператора AND, и это невозможно. Но мы можем создать суперразмерный RegExp, который распознает все возможные случаи. Но тип типа RegExp в шляпе бессмыслен, потому что это займет много времени, чтобы применить этот тест к вашей строке. Я бы рекомендовал вам выполнить три отдельных теста:
var result = string.replace(/[A-Za-z]{6}/, "").replace(/[0-9]{2}/, "").replace(/[A-Za-z0-9#,\.\-]{6}/, "").length == 0 ? true : false; // By shortening our sting we're saving time on later chained replacement methods