PHP正则:如何基于[:graph:]排除黑名单并扩展白名单字符?
问题分析与解决方案
你的代码问题主要出在正则模式的构建上,同时没考虑白名单的处理逻辑,以下是具体修正方案:
核心问题点
- 正则语法错误:你写的
[{".preg_quote($blacklist, '')."}]+会把{和}当作字面量字符匹配,导致额外删除这两个符号,正确的写法应该是直接用[{$escaped_blacklist}]+`来匹配黑名单内的字符。 - 白名单未处理:原代码会移除所有非
[:graph:]的字符,包括你想保留的白名单字符(比如空格),需要把白名单加入到「不被移除」的集合中。
修正后的完整代码
// 示例参数,可根据实际需求修改 $length = 12; $blacklist = '~`'; // 需要排除的字符 $whitelist = ' '; // 需要额外允许的字符(如空格) // 转义特殊字符,适配正则语法 $escaped_blacklist = preg_quote($blacklist, '`'); $escaped_whitelist = preg_quote($whitelist, '`'); // 构建正则模式 if (empty($blacklist) && empty($whitelist)) { // 基础场景:仅保留[:graph:]字符 $pattern = '`[^[:graph:]]+`s'; } elseif (empty($blacklist)) { // 仅添加白名单:保留[:graph:] + 白名单字符 $pattern = "`[^[:graph:]{$escaped_whitelist}]+`s"; } elseif (empty($whitelist)) { // 仅排除黑名单:保留[:graph:] 减去 黑名单字符 $pattern = "`(?:[^[:graph:]]+|[{$escaped_blacklist}]+)`s"; } else { // 同时处理黑名单和白名单:保留[:graph:]减黑名单 + 白名单,删除其余字符 $pattern = "`(?:[^[:graph:]{$escaped_whitelist}]+|[{$escaped_blacklist}]+)`s"; } // 生成符合要求的随机字符串 $secure_password = substr(preg_replace($pattern, "", random_bytes($length * 10)), 0, $length);
代码说明
- 字符转义:用
preg_quote处理黑名单和白名单字符,避免正则特殊字符(如^、-、])破坏语法结构,第二个参数指定正则分隔符`,确保分隔符本身被正确转义。 - 模式逻辑:
- 当无黑名单和白名单时,沿用你原本的基础模式。
- 仅加白名单时,修改否定字符组为
[^[:graph:]{$escaped_whitelist}],确保白名单字符不被移除。 - 仅排除黑名单时,用
(?:[^[:graph:]]+|[{$escaped_blacklist}]+)匹配「非[:graph:]字符」或「黑名单字符」,统一替换为空。 - 同时处理两者时,合并上述逻辑,确保最终只保留你需要的字符集合。
内容的提问来源于stack exchange,提问作者carlo-849978
相关产品推荐
相关产品推荐

