PHP中的“filter_var”和“preg_replace”的后端区别是什么?

3

我需要从数据库中提取数字(非常有限制的输入),这些数字在前后会有下划线。它们存储的方式如下:

_51_ _356_

它们不会以任何其他格式存储,但有时我需要仅提取其中的数字。我选择使用以下之一:

$x = filter_var($myNumber, FILTER_SANITIZE_NUMBER_INT);

或者

$y = preg_replace("/[^0-9]/","",$myNumber);

我不确定后端两者之间的区别,但它们都可以生成我需要的内容(至少我认为是这样),所以对我来说使用哪个并不重要。使用每个选项的优缺点是什么?(例如,是否使用数组或其他我可能需要了解的奇怪东西?其中一个使用了过多资源?)


尽可能使用字符串函数而不是正则表达式函数,例如使用str_replace()或trim()。 - Konstantin
2
基准测试一下。这两种解决方案完全不同。FILTER_SANITIZE_NUMBER_INT只做它所说的事情。preg是一个完整的正则表达式引擎,你只使用了其中的一小部分功能。其中一种可能比另一种更有效,但唯有通过基准测试才能确认。 - deceze
2
在对其进行基准测试之前,添加量词“+”以获得更高效的模式。 - Casimir et Hippolyte
3个回答

2

在您的情况下,这并没有太大的区别。我认为preg_replace在资源方面更昂贵,因为它必须解析正则表达式模式。

或者您可以使用trim

echo trim('_12_', '_');

它将删除两侧的“_”符号,我认为这是最易读的方法。

我会研究一下 trim()。也许我会使用它。 - BillyNair

2

过滤器不使用正则表达式,但工作方式类似:逐个字符迭代字符串并删除与模式不匹配的字符:

for (i = 0; i < Z_STRLEN_P(value); i++) {
    if ((*map)[str[i]]) {
        buf[c] = str[i];
        ++c;
    }
}

@http://lxr.php.net/xref/PHP_5_6/ext/filter/sanitizing_filters.c#filter_map_apply

FILTER_SANITIZE_NUMBER_INT 被定义为 [^0-9+-]:

/* strip everything [^0-9+-] */
const unsigned char allowed_list[] = "+-" DIGIT;
filter_map     map;

filter_map_init(&map);
filter_map_update(&map, 1, allowed_list);
filter_map_apply(value, &map);

@http://lxr.php.net/xref/PHP_5_6/ext/filter/sanitizing_filters.c#php_filter_number_int

当然,[^0-9+-]不是正确的表达式来过滤整数,因此要准备好惊喜:

$x = filter_var("+++123---", FILTER_SANITIZE_NUMBER_INT);
var_dump($x); // WTF?

我的建议是坚持使用正则表达式:它们更加明确,而且比过滤器更少出现错误。


1

我想尝试一些不同的方法,因此设置了以下基准。看起来对于您的情况,trim显然是最好的选择,因为它只需查看字符串的开头和结尾而不是每个字符。以下是在PHP 7.0.18上运行的1000万个随机整数用下划线括起来的测试结果。

preg_replace:1.9469740390778秒。

filter_var:1.6922700405121秒。

str_replace:0.72129797935486秒。

trim:0.37275195121765秒。

如果有人想运行类似的测试,这是我的代码:

<?php
$ints = array();//array_fill(0, 10000000, '_1029384756_');
for($i = 0; $i < 10000000; $i++) {
$ints[] = '_'.mt_rand().'_';
}

$start = microtime(true);
foreach($ints as $v) {
preg_replace('/[^0-9]/', '', $v);
}
$end = microtime(true);
echo 'preg_replace in '.($end-$start).' seconds.',PHP_EOL;

$start = microtime(true);
foreach($ints as $v) {
filter_var($v, FILTER_SANITIZE_NUMBER_INT);
}
$end = microtime(true);
echo 'filter_var in '.($end-$start).' seconds.',PHP_EOL;

$start = microtime(true);
foreach($ints as $v) {
str_replace('_', '', $v);
}
$end = microtime(true);
echo 'str_replace in '.($end-$start).' seconds.',PHP_EOL;

$start = microtime(true);
foreach($ints as $v) {
trim($v, '_');
}
$end = microtime(true);
echo 'trim in '.($end-$start).' seconds.',PHP_EOL;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接