str_shuffle()仅适用于ascii字符串,utf-8多字节字符需用preg_match_all('/./u')拆分后shuffle()再implode();需可重现结果时须手动设随机种子,且注意保留原始空白与不可见字符。

PHP 用 str_shuffle() 最简单,但只支持 ASCII 字符
直接调用 str_shuffle() 就能打乱字符串顺序,它内部用的是 C 的 rand(),对纯英文、数字、ASCII 符号完全够用。
常见错误现象:中文、emoji、UTF-8 多字节字符打乱后变成乱码或截断——因为 str_shuffle() 按字节操作,不是按字符。
- 只适合
"abc123"、"hello_world"这类纯 ASCII 字符串 - 遇到
"你好"或"??",结果不可预测,别硬套 - 不需要额外安装扩展,PHP 4.0+ 原生支持
UTF-8 字符串必须先拆成字符数组再打乱
中文、日文、emoji 等多字节字符得用 mb_substr() 或正则逐个提取,再用 shuffle() 打乱数组,最后拼接。
性能影响:比 str_shuffle() 慢 3–5 倍(尤其长文本),但这是正确处理 UTF-8 的唯一可靠方式。
立即学习“PHP免费学习笔记(深入)”;
- 别用
str_split(),它不识别 UTF-8,会把一个汉字切成两三个字节 - 推荐用
preg_match_all('/./u', $str, $matches)提取字符,兼容性最稳 - 示例:
$chars = preg_match_all('/./u', $str, $m) ? $m[0] : []; shuffle($chars); $shuffled = implode('', $chars);
需要可重现的随机结果?别依赖默认随机数种子
str_shuffle() 和 shuffle() 都依赖 PHP 当前的随机数状态,每次运行结果不同。如果要做测试、缓存键生成或需要确定性输出,必须手动设种子。
- PHP 7.1+ 推荐用
random_int()+mt_srand()控制:mt_srand(12345); $shuffled = str_shuffle($str); - PHP 8.2+ 可用
Random\Randomizer类,更安全但稍重:$r = new Random\Randomizer(new Random\Engine\Mt19937(12345)); $chars = $r->shuffleArray($charArray); - 注意:
mt_srand()是进程级的,多线程或 FPM 下慎用全局设种
打乱后还要保留原始字符集?小心大小写和空格被忽略
有些需求是“仅打乱顺序,其他一模一样”,比如密码生成、混淆日志。但实际容易漏掉空白、不可见字符(如 \t、\n、零宽空格)。
-
preg_match_all('/./u')默认不匹配换行符,要加s修饰符:/./us - 如果字符串含 BOM 或控制字符,建议先用
mb_convert_encoding($str, 'UTF-8', 'UTF-8')归一化编码 - 测试时用
bin2hex($str)对比打乱前后字节是否一致,避免意外丢字符











