电话
400 9058 355
strlen()按字节计数,制表符\t在UTF-8中占1字节,故长度为1;视觉宽度需按tabstop模拟列偏移计算,如tabstop=4时,“a\t”视觉长度为4。
\t 当作 1 个字节算PHP 的 strlen() 是按字节计数的,\t 在 UTF-8 编码下就是单字节(ASCII 值为 9),所以它和普通英文字符一样,长度为 1。这和你“肉眼看到的缩进宽度”无关——制表符本身不等于 4 个空格,只是终端/编辑器渲染时可能显示为 4 列宽。
如果你用 strlen("a\tb"),结果是 3,不是 5(哪怕它在 IDE 里看起来像 “a b”)。
所谓“含制表符的视觉长度”,本质是把每个 \t 替换成若干空格,再算总字符数。但空格数取决于当前列位置,不是固定值。比如:
"\t" 在开头 → 从第 0 列开始,通常补到第 4 列 → 算 4 个空格"a\t":'a' 占第 0 列,\t 从第 1 列起,补到下一个 4 的倍数(即第 4 列)→ 补 3 个空格"ab\t":'a','b' 占 0、1 列,\t 从第 2 列起 → 补 2 个空格标准做法是模拟制表位(如每 4 列一个),逐字符遍历并维护当前列偏移:
// 示例:按 tabstop=4 计算显示宽度
function visual_strlen($str, $tabstop = 4) {
$len = 0;
for ($i = 0; $i < strlen($str); $i++) {
$c = $str[$i];
if ($c === "\t
") {
$len += $tabstop - ($len % $tabstop);
} else {
$len++;
}
}
return $len;
}\t 没影响,别指望它“修正”制表符mb_strlen() 是为多字节字符(如中文、emoji)设计的,它依然把 \t 当作 1 个“字符”(code unit),不会改变其计数逻辑。无论你传 'UTF-8' 还是 '8bit',mb_strlen("a\tb") 还是 3。
它解决的是 "我" 这种在 UTF-8 下占 3 字节但应算作 1 个字符的问题,不是制表符渲染宽度问题。
用户粘贴进来的文本、读取的配置文件、HTTP 请求体,都可能含真实 \t。如果你的业务逻辑依赖“显示宽度”(比如限制输入框可见长度、对齐日志输出、生成等宽表格),就不能只靠 strlen()。
white-space: pre 渲染?后端校验就得用 visual_strlen() 对齐strlen() 更轻量,也更符合 HTTP 协议层的字节语义\r\n 中的 \r 和 \n 各算 1 字节,同样不参与“视觉宽度”计算,但会影响列偏移逻辑制表符的“长度歧义”不在 PHP 函数缺陷,而在你没明确区分「存储长度」「编码字符数」「终端显示宽度」这三个概念。选哪个,取决于你的上下文到底要约束什么。
邮箱:8955556@qq.com
Q Q:8955556
本文详解如何将Go官方present工具(用于生成HTML5...
PySNMP在不同版本中对SNMP错误状态(errorSta...
time.Sleep仅阻塞当前goroutine,其他gor...
PHPfopen()创建含特殊符号的文件名失败主因是操作系统...
WooCommerce中通过代码为分组产品动态聚合子商品的属...
io.ReadFull返回io.ErrUnexpectedE...
本文详解Yii2中控制器向视图传递ActiveRecord数...
本文详解为何通过wp_set_object_terms()为...
Pytest中使用@mock.patch类装饰器会导致补丁泄...
带缓冲的channel是并发安全的FIFO队列;make(c...