macOS上df無法正確顯示中文

最近心血來潮,把工作環境設定為中文。在Linux下是開一個檔案~/.config/locale.conf,寫入LANG=zh_TW.UTF-8。macOS下,iTerm2會自動設定LANGLC_CTYPE這兩個環境變數。

第一個出現問題的是zsh下,ssh的hostname自動完成。按下tab後,游標會自動往前一格。目前還沒查出問題來。

第二個問題是macOS下的df中文顯示錯亂。由於GNU coreutils整體上比mac內建的指令好用,因此我長久以來都是用MacPorts安裝的coreutils。

今天環境改成中文時,df出現怪異的輸出:

�?�?系統 容�?? 已�?� �?��?� 已�?�% �??�?�?
/dev/disk1s1    234G  151G    81G    65% /
/dev/disk1s4    234G  2.1G    81G     3% /private/var/vm

這串文字丟進python encode後的結果是:

b'\xe6\xaa?\xe6\xa1?\xe7\xb3\xbb\xe7\xb5\xb1 \xe5\xae\xb9\xe9?? \xe5\xb7\xb2\xe7?\xa8 \xe5?\xaf\xe7?\xa8 \xe5\xb7\xb2\xe7?\xa8% \xe6??\xe8\xbc?\xe9\xbb?'

正確版本應該是:

b'\xe6\xaa\x94\xe6\xa1\x88\xe7\xb3\xbb\xe7\xb5\xb1 \xe5\xae\xb9\xe9\x87\x8f \xe5\xb7\xb2\xe7\x94\xa8 \xe5\x8f\xaf\xe7\x94\xa8 \xe5\xb7\xb2\xe7\x94\xa8% \xe6\x8e\x9b\xe8\xbc\x89\xe9\xbb\x9e'

可以看出,某些byte被換成問號了。

Google了一番,沒啥結果。決定自行把coreutils抓下來compile,再丟到lldb debug。一番努力之後,發現df的hide_problematic_chars()會把iscntrl()回傳1的字元換成問號。這個函數在Linux上是正常的,但在mac上,卻會受到locale影響。我寫了一個小程式測試:

#include <locale.h>
#include <stdio.h>
#include <ctype.h>

int main()
{
    printf("%d\n", iscntrl(148));
    setlocale(LC_ALL, "");
    printf("%d\n", iscntrl(148));
    return 0;
}

在Linux上,輸出0 0,而在mac上輸出0 1。

目前先自行編一個hide_problematic_chars()改過的版本將就用著,等有空再向GNU提bug。

2020/11/08更新:

  • 向coreutils提交了一份bug report,接著我的patch被修改後commit到coreutils了!
  • zsh中ssh tab補全似乎已經修好了。

social