使用preg_replace
,如何将多个下划线替换为一个下划线?
+
运算符(量词) 匹配最后一个字符(或字符类或捕获组或反向引用)的多个实例。
$string = preg_replace('/_+/', '_', $string);
这会将一个或多个下划线替换为一个下划线。
从技术上讲,更符合问题标题的做法是仅替换两个或更多下划线:
$string = preg_replace('/__+/', '_', $string);
或使用花括号写量词:
$string = preg_replace('/_{2,}/', '_', $string);
$string = preg_replace('/(_)\1+/', '\1', $string);
preg_replace('/[_]+/', '_', $your_string);
实际上,使用/__+/
或/_{2,}/
比使用/_+/
更好,因为单个下划线不需要被替换。这将提高preg变量的速度。
运行测试,我发现了这个问题:
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()
始终更快。
我知道有些人可能因为其他原因而更喜欢一种方法,而不是速度,我很乐意阅读有关结果、测试方法等方面的评论。
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
+
,因为它会造成不必要的替换(_
变成了_
)。echo preg_replace('/_+/', '_', $str);
使用字符类 或 /[_]+/
绝对没有好处。/[_]{2,}/
使用 preg_replace()
的好处是字符串只被遍历一次。这使它成为一个非常直接和适当的工具。