字符串与正则表达式匹配的百分比

时间:2014-04-30 21:44:58

标签: php regex

基本上,我只是想知道是否存在这样的函数:

$string = 'helloWorld';

// 1 uppercase, 1 lower case, 1 number and at least 8 of length
$regex = '/^\S*(?=\S{8,})(?=\S*[a-z])(?=\S*[A-Z])(?=\S*[\d])\S*$/'

$percent = matchPercent($string, $regex);

echo "the string match {$percent}% of the given regex";

然后,结果可能是这样的:

  

字符串匹配给定正则表达式的75%

看到另一篇文章和问题,我可以这样做:

$uppercase = preg_match('@[A-Z]@', $password);
$lowercase = preg_match('@[a-z]@', $password);
$number    = preg_match('@[0-9]@', $password);

但是,目标是在函数

处使用任何正则表达式模式

2 个答案:

答案 0 :(得分:5)

如果你想以正则表达式的方式并根据你提供的用例,我们需要使整个正则表达式可选。此外,我们将在我们的前瞻中使用捕获组。

但首先,让我们改进你的正则表达式:

  • [\d]是多余的,只需使用\d
  • \S*(?=\S{8,})删除\S*部分,我们已经在最后删除了它。

我们的正则表达式看起来像^(?=\S{8,})(?=\S*[a-z])(?=\S*[A-Z])(?=\S*\d)\S*$

现在是棘手的部分,我们将在我们的前瞻中添加组并使它们成为可选项:

^(?=(\S{8,})?)(?=(\S*[a-z])?)(?=(\S*[A-Z])?)(?=(\S*\d)?)\S*$

你可能会问为什么?这些组是为了以后我们可以跟踪它们。我们将它们设为可选项,以便我们的正则表达式始终匹配。这样,我们可以做一些数学!

$regex = '~^(?=(\S{8,})?)(?=(\S*[a-z])?)(?=(\S*[A-Z])?)(?=(\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;

Online php demo

答案 1 :(得分:2)

编辑:我看到Hamza几乎有同样的想法。

当然!这是一个非常有趣的问题。

这是简化验证正则表达式的解决方案。

$str = 'helloword';
$regex = '~^(?=(\S{8,}))?(?=(\S*[a-z]))?(?=(\S*[A-Z]))?(?=(\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. 我们分开。