Raku如何避免调用tree命令时出现Malformed UTF-8错误
问题根因
- Raku 的
run/shell调用启动子进程时,不会加载 zsh 的交互配置,子进程继承的系统基础环境未设置 UTF-8 相关的 locale 变量,和你在终端直接运行命令的环境不一致 - 你遇到的
Malformed UTF-8报错,本质是 tree 在非 UTF-8 locale 下输出了非 UTF-8 编码的制表符(对应报错里的ef b9 5c非法字节序列) - 之前尝试的
utf8-c8编码、临时文件重定向方案无效,是因为 tree 输出本身根本不是 UTF-8 编码序列,无论用什么编码读取原始字节都会触发解码错误
可直接运行的解决方案
方案1:直接强制 tree 输出 UTF-8 内容(推荐)
GNU tree 原生支持通过参数指定输出字符集,不需要修改全局环境变量:
my $proc = run( 'tree', '--du', '--charset=utf-8', :out); # 读取时显式指定按UTF-8解码 $proc.out.slurp(:close, enc => 'utf8').say;
方案2:给子进程显式传入UTF-8 locale环境
如果你的 tree 版本不支持 --charset 参数,可以在调用时主动给子进程传入正确的环境变量,强制 tree 输出 UTF-8 内容:
# 克隆当前环境并补充UTF-8 locale配置 my %proc-env = %*ENV.clone; %proc-env<LANG> = 'en_US.UTF-8'; %proc-env<LC_ALL> = 'en_US.UTF-8'; my $proc = run( 'tree', '--du', :out, :env(%proc-env)); $proc.out.slurp(:close, enc => 'utf8').say;
可通过终端执行
locale -a查询你系统上可用的UTF-8 locale名称,替换示例中的en_US.UTF-8即可。
修正后的临时文件方案
如果需要沿用之前的临时文件逻辑,需要同步修正两点:一是给 tree 调用显式传入UTF-8配置,二是打开文件时指定正确的编码:
shell( "LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 tree --du >> .temp.txt" ); # 打开文件时显式指定UTF-8编码,避免默认解码错误 my @lines = open(".temp.txt", enc => 'utf8').lines; dd @lines;
注意事项
- 不要使用
utf8-c8编码参数,该编码仅用于处理合法UTF-8序列中夹杂少量非法字节的场景,对完全非UTF8的输入无效 - 你之前在终端直接运行tree能正常输出,是因为zsh的交互配置已经设置了正确的locale变量,Raku调用的非交互子进程不会自动加载这些配置,必须显式指定
内容的提问来源于stack exchange,提问作者librasteve
相关产品推荐
相关产品推荐

