PHP:非preg_match版本:preg_match(“/ [^ a-z0-9] / i”,$ a,$ match)?

时间:2016-02-23 13:13:57

标签: php preg-match

据说字符串是:

$a = "abc-def"


if (preg_match("/[^a-z0-9]/i", $a, $m)){
  $i = "i stopped scanning '$a' because I found a violation in it while 
  scanning it from left to right. The violation was: $m[0]";
}

echo $i;

上面的例子:应该表明“ - ”是违规行为。

我想知道是否存在非preg_match方式。

如果有非preg_match方式可能会运行1000或100万次运行,我可能会运行基准测试,以查看哪种更快更有效。

在基准测试中,“$ a”会更长。 确保它不会扫描整个“$ a”并确保它很快就会停止,因为它会在“$ a”中检测到违规行为

根据我在互联网上目击的信息,preg_match会在找到第一个匹配时停止。

更新

这是基于“主教”给出的答案,很快就会被选为有效答案。(很快)。

我修改了一下因为我只想报告违规者字符。但我也评论说,基线可以在没有纠缠的情况下运行。

让我们根据答案运行100万次。

$start_time = microtime(TRUE);

$count = 0;
while ($count < 1000000){

$allowed = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
$input   = 'abc-def';

$validLen = strspn($input, $allowed);
if ($validLen < strlen($input)){
    #echo "violation at: ". substr($input, $validLen,1);
}

$count = $count + 1;
};

$end_time = microtime(TRUE);
$dif = $end_time - $start_time;

echo $dif;

结果是:0.606614112854 (60%的一秒)

让我们用preg_match方法做。

我希望一切都是一样的。 (公平).. (我说这是因为preg_match中有^字符)

$start_time = microtime(TRUE);

$count = 0;
while ($count < 1000000){

$input   = 'abc-def';
preg_match("/[^a-z0-9]/i", $input, $m);
#echo "violation at:". $m[0];

$count = $count + 1;
};

$end_time = microtime(TRUE);
$dif = $end_time - $start_time;

echo $dif;

我使用“dif”来引用术语“差异”。

“dif”是.. 1.1145210266113

(比一秒多花了11%)

(如果它是1.2意味着它比php方式慢2倍)

1 个答案:

答案 0 :(得分:3)

您想要在给定范围内找到第一个字符而不是的位置,而不使用正则表达式?您可能需要strspn或其补充strcspn

$allowed = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
$input   = 'abc-def';

$validLen = strspn($input, $allowed);
if (strlen($input) !== $validLen) {
    printf('Input invalid, starting at %s', substr($input, $validLen)); 
} else {
    echo 'Input is valid';
}

输出Input invalid, starting at -defSee it live

strspn(及其补充)非常陈旧,非常明确(POSIX甚至)。标准实现针对此任务进行了优化。 PHP只是利用了该平台实现,因此PHP也应该很快。