PHP : non-preg_match version of: preg_match("/[^a-z0-9]


PHP : non-preg_match version of: preg_match("/[^a-z0-9]/i", $a, $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停止。

更新:

这是基于"主教"给出的答案,并且可能很快就会被选为有效答案(不久)。

我稍微修改了一下,因为我只想让它报告违规者角色。 但我也注释了那行,以便 Benchmark 可以在没有纠缠的情况下运行。

让我们根据这个答案运行 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 倍)

您想在不使用正则表达式的情况下找到不在给定范围内的第一个字符的位置?您可能需要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 -def .现场观看。

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