Сколько процентов строки соответствует регулярному выражению

В принципе, мне просто интересно, существует ли такая функция:

$string = 'helloWorld'; // 1 uppercase, 1 lower case, 1 number and at least 8 of length $regex = '/^\S*(?=\S{8,})(?=\S*[az])(?=\S*[AZ])(?=\S*[\d])\S*$/' $percent = matchPercent($string, $regex); echo "the string match {$percent}% of the given regex"; 

Тогда результат может быть примерно таким:

строка соответствует 75% заданного регулярного выражения

Увидев еще одно сообщение и вопрос, я могу сделать что-то вроде этого:

 $uppercase = preg_match('@[AZ]@', $password); $lowercase = preg_match('@[az]@', $password); $number = preg_match('@[0-9]@', $password); 

Но цель состоит в том, чтобы работать с любым шаблоном регулярного выражения в функции

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

Но сначала сначала, давайте улучшим ваше регулярное выражение:

  • [\d] является избыточным, просто используйте \d .
  • \S*(?=\S{8,}) удаляем \S* часть, мы уже имеем ее в конце.

Наше регулярное выражение будет выглядеть как ^(?=\S{8,})(?=\S*[az])(?=\S*[AZ])(?=\S*\d)\S*$

Теперь это сложная часть, мы добавим группы в наши взгляды и сделаем их необязательными:

^(?=(\S{8,})?)(?=(\S*[az])?)(?=(\S*[AZ])?)(?=(\S*\d)?)\S*$

Вы можете спросить, почему? Группы создаются так, что мы можем отслеживать их позже. Мы делаем их необязательными, чтобы наше регулярное выражение всегда соответствовало. Таким образом, мы можем сделать математику!

 $regex = '~^(?=(\S{8,})?)(?=(\S*[az])?)(?=(\S*[AZ])?)(?=(\S*\d)?)\S*$~'; $input = 'helloWorld'; preg_match_all($regex, $input, $m); array_shift($m); // Get rid of group 0 for($i = 0, $j = $k = count($m); $i < $j; $i++){ // Looping if(empty($m[$i][0])){ // If there was no match for that particular group $k--; } } $percentage = round(($k / $j) * 100); echo $percentage; 

Демо-версия

EDIT: Я вижу, что у Хамзы была почти такая же идея.

Конечно! Это очень забавный вопрос.

Вот решение для упрощенного регулярного выражения.

 $str = 'helloword'; $regex = '~^(?=(\S{8,}))?(?=(\S*[az]))?(?=(\S*[AZ]))?(?=(\S*[\d]))?.*$~'; if(preg_match($regex,$str,$m)) { $totaltests = 4; $passedtests = count(array_filter($m)) -1 ; echo $passedtests / $totaltests; } 

Выход: 0,5

Как это работает?

  1. Для каждого условия (выраженного взглядом) мы фиксируем текст, который можно сопоставить.
  2. Мы определяем $totaltests как общее количество тестов
  3. Мы подсчитываем количество тестов, прошедших с count(array_filter($m)) -1 который удаляет пустые группы и группу 0, то есть общее совпадение.
  4. Мы делимся.