我如何使用preg_replace
,用一个下划线替换多个下划线?
7 回答
+
运算符(量词)匹配最后一个字符的多个实例(字符类或捕获组或反向引用)。
$string = preg_replace('/_+/', '_', $string);
这将用一个下划线替换一个或多个下划线。
从技术上讲,对问题的标题更正确的是只替换两个或更多:
$string = preg_replace('/__+/', '_', $string);
或者用大括号写量词:
$string = preg_replace('/_{2,}/', '_', $string);
$string = preg_replace('/(_)\1+/', '\1', $string);
preg_replace('/[_]+/', '_', $your_string);
运行测试,我发现了这个:
while (strpos($str, '__') !== false) {
$str = str_replace('__', '_', $str);
}
始终比这更快:
$str = preg_replace('/[_]+/', '_', $str);
我用这个生成了不同长度的测试字符串:
$chars = array_merge(array_fill(0, 50, '_'), range('a', 'z'));
$str = '';
for ($i = 0; $i < $len; $i++) { // $len varied from 10 to 1000000
$str .= $chars[array_rand($chars)];
}
file_put_contents('test_str.txt', $str);
并使用这些脚本进行测试(单独运行,但对于$len的每个值都使用相同的字符串):
$str = file_get_contents('test_str.txt');
$start = microtime(true);
$str = preg_replace('/[_]+/', '_', $str);
echo microtime(true) - $start;
和:
$str = file_get_contents('test_str.txt');
$start = microtime(true);
while (strpos($str, '__') !== false) {
$str = str_replace('__', '_', $str);
}
echo microtime(true) - $start;
对于较短的字符串,该str_replace()
方法比该preg_replace()
方法快 25%。字符串越长,差异越小,但str_replace()
总是更快。
我知道有些人会因为速度以外的原因更喜欢一种方法,我很乐意阅读有关结果、测试方法等的评论。
实际上使用/__+/
or/_{2,}/
会更好,/_+/
因为不需要替换单个下划线。这将提高 preg 变体的速度。
对于因基准/微优化原因而被@GZipp 的答案吸引的任何人,我认为以下测试后循环应该比测试前循环执行得稍好,while()
因为strpos()
调用已被删除。
str_replace()
有一个引用变量参数,可用于中断循环,而无需额外的迭代函数调用。当然,它总是会尝试至少进行一次替换,并且在遍历没有替换的字符串之前它不会停止。
代码:(演示)
$str = 'one_two__three___four____bye';
do {
$str = str_replace('__', '_', $str, $count);
} while ($count);
var_export($str);
// 'one_two_three_four_bye'
至于preg_replace()
,这里有几个不错的选择:
echo preg_replace('/_{2,}/', '_', $str);
echo preg_replace('/_\K_+/', '', $str); // \K forgets the first, remembers the rest
我不建议使用+
,因为它会进行不必要的替换 ( _
to _
)
echo preg_replace('/_+/', '_', $str);
使用字符类或/[_]+/
./[_]{2,}/
使用的好处preg_replace()
是字符串永远不会被遍历超过一次。这使它成为一个非常直接和合适的工具。
您还可以使用具有自动分隔符的 T-Regx 库。
pattern('_+')->replace($your_string)->with('_');