ANSI 跳脫碼是由控制位元組組成的序列,以 ESC 字元 (十進位 27,十六進位 0x1B) 開頭,後接左方括號、一個或多個以分號分隔的 Select Graphic Rendition (SGR) 參數,以及字母 m,用來變更其後字元的前景顏色、背景顏色與文字樣式。一個典型的完整序列寫成 ESC[<params>m<text>ESC[0m,其中尾端的重設會在彩色文字印出後清除任何作用中的格式設定。ESC 位元組本身是不可見的;讓終端機辨識出跳脫碼的是帶有方括號的參數區塊,而不是頁面上可列印的字元。ECMA-48 標準化了格式與基礎呈現控制,而 xterm 文件交叉核對了大多數 Linux 與 macOS 終端機模擬器所採用的明亮色對應。當你撰寫腳本或除錯樣板時,可以手動建構這些位元組,但像 ANSI Color Codes Generator 這類工具讓你輸入文字、選擇是否設定前景、背景、粗體與底線,並複製一個終端機感知消費者所預期的精確原始控制位元組字串。

ansi escape codes
ansi escape codes

ANSI 跳脫碼的格式

Control Sequence Introducer (CSI) 是現代終端機中最常見的 ANSI 跳脫碼形式。它由 ESC 接著左方括號、零個或多個以分號分隔的數值參數,以及一個命名該操作的結尾位元組所組成。字母 m 代表 SGR 作業;其他字母如 H、J、K 或 A 則執行游標移動、螢幕清除或行清除,但這些不在顏色與樣式的討論範圍內。

最基本的 SGR 形式是 ESC[0m,它會重設所有作用中的圖形呈現。僅設定前景顏色時使用一個參數,例如 ESC[31m 代表第二個基礎前景位置 (紅色)。結合多個屬性時會堆疊參數:ESC[1;4;91;44m 會開啟粗體、開啟底線、設定亮紅色前景 (91),並設定藍色背景 (44)。終端機會一次套用所有列出的屬性,並持續記住直到新的前綴或重設指令出現。

從這個結構可以得出兩個實用的注意事項。第一,參數是十進位整數;終端機不會解析十六進位、八進位或符號形式。第二,m 結尾符號是必要的;如果沒有它,終端機會繼續將位元組當作參數讀取,導致序列被忽略,或在下游產生非預期的動作。ANSI Color Codes Generator 一律會輸出完整的前綴與附加的 ESC[0m 重設,因此帶方括號的參數區塊是平衡的,作用中的呈現會在位元組流的正確位置結束。

SGR 參數的組織方式

SGR 參數遵循固定的數字對應表。樣式參數切換屬性,顏色參數選擇調色盤位置。ECMA-48 定義了基礎呈現控制;xterm 控制序列文件交叉核對了多數現代模擬器在該基礎上實作的明亮色對應。

代碼意義
0重設所有屬性
1粗體 (或在某些終端機上為加強亮度)
4底線
30-37基礎前景調色盤:黑、紅、綠、黃、藍、洋紅、青、白
40-47同樣八色的基礎背景調色盤
90-97明亮前景調色盤 (xterm 相容延伸)
100-107明亮背景調色盤 (xterm 相容延伸)

30-37 的基礎範圍與其 40-47 背景對應,是每個符合規範的終端機都必須接受的八個調色盤位置。90-97 與 100-107 範圍是多數 Linux 與 macOS 模擬器支援、但 ECMA-48 並未強制要求的延伸。產生器會拒絕不支援的樣式或顏色編號,以確保產生的序列在不同消費者之間保持可攜性。

有一個值得記住的細節:顏色編號選擇的是調色盤位置,而不是精確的 RGB 值。實際在螢幕上顯示的顏色取決於終端機主題、使用者無障礙設定、多工器,以及在你的腳本與使用者之間可能重新對應這些位置的遠端環境。產生器刻意不顯示假的瀏覽器內色彩預覽,因為那會暗示存在一個不存在的單一通用終端機調色盤。

為什麼產生器對 ANSI 跳脫碼有幫助

在記住參數對應表後,手寫 SGR 序列很簡單,但很容易出貨時帶著錯誤。缺少方括號、使用字面反斜線序列而非 ESC 位元組,或忘記重設,都會讓下一段輸出以你沒有意料的方式格式化,而這個 bug 通常只會出現在你沒有在本機測試過的下游終端機中。ANSI Color Codes Generator 的可見輸出會將跳脫位元組寫成 \x1b,讓序列可以在瀏覽器中檢視而不改變頁面本身的外觀;底層的控制位元組仍會如終端機所預期地產生。

這帶來三個實際好處。你可以查詢 16 色參考表,而不必記住哪個整數對應哪個顏色位置。你可以僅套用必要的小集合參數,而不是輸出所有屬性,這能讓日誌樣板保持簡短且易讀。而且你只需複製原始跳脫序列,因為產生器已經驗證過參數並附加了重設。原始跳脫位元組是控制資料,將它們貼到錯誤的地方 (例如聊天訊息、行內註解或問題追蹤系統) 會產生不可見的行為,而不是可讀的文字。Copy raw sequence 按鈕會將實際的 ESC 控制位元組加上參數、加上文字、再加上重設,放到剪貼簿中,而不是四個可見字元 backslash-x-1-b。

對於臨時除錯、撰寫腳本或樣板而言,這消除了手寫 ANSI 輔助程式時常出現的一整類差一錯誤。對於較大的專案,同樣的模式可以作為有用的基準;每當你的程式庫開始手動組合 ESC 位元組時,你都可以根據產生器輸出的內容逐字元比對驗證結果。

如何使用 ANSI Color Codes Generator 建立 SGR 序列

  1. 在瀏覽器中開啟 ANSI Color Codes Generator,並在輸入欄位中輸入你想格式化的終端機文字。
  2. 從基礎或明亮調色盤中選擇一個選用的前景、一個選用的背景,並視需要切換粗體或底線。如果不想要該屬性,將設定留空即可。
  3. 產生序列。可見的跳脫表示法會將跳脫位元組寫成 \x1b 讓你能閱讀,SGR 參數面板會顯示實際輸出的精確十進位數字。
  4. 使用 Copy 按鈕複製原始序列。剪貼簿中現在包含實際的 ESC 位元組加上帶方括號的參數、加上你的文字、再加上結尾的 ESC[0m 重設。
  5. 只貼入可信任且具終端機感知能力的情境:腳本中的來源字串、樣板檔案、REPL、除錯器,或正由終端機感知消費者檢視的 CI 日誌。
  6. 透過在格式化文字之後印出其他內容來測試重設行為。下一個可見字元應以預設樣式顯示,這可確認尾端的 ESC[0m 重設已清除作用中的呈現。

一個實際範例:選擇亮紅色前景、藍色背景、粗體與底線,會產生參數字串 1;4;91;44。產生器會輸出 ESC[1;4;91;44m<your text>ESC[0m,典型 xterm 相容模擬器會將其呈現為藍色背景上的粗體加底線亮紅色文字,然後在重設位元組之後立即恢復為預設樣式。

日誌與未受信任文字中的跳脫碼

原始跳脫序列是控制資料,不是可列印字元。將它們貼到終端機命令列、聊天記錄、記錄檔或來源註解中,可能會產生不可見的行為,而不是可讀的文字。由於 ESC 位元組沒有字形,在網頁或基本文字檢視器中,格式化輸出看起來就像普通字元,但它會在互動式終端機內執行副作用:游標移動、顏色變更、螢幕清除,或隱藏部分行的文字重排。

包含未受信任控制位元組的日誌是已記載的風險。攻擊者可以隱藏文字、偽造指向誤導連結的視覺行、建立假狀態指示,或擾亂下一個開啟檔案之使用者的終端機狀態。將未受信任文字中的任何控制位元組視為潛在惡意。在列印到互動式終端機之前先清理資料,並提供一條純文字日誌路徑,將控制序列移除或明顯跳脫,例如寫成 \x1b 而非該位元組本身。

產生器的幫助在於將可見表示法寫成 \x1b,但一旦你按下 Copy raw sequence,剪貼簿中就會有真實的控制位元組。在貼上之前,先問問自己目的地會是由解讀 SGR 的終端機感知消費者開啟、由逐字顯示位元組的純文字編輯器開啟,還是由移除控制字元的下游日誌管道開啟。同一個序列在腳本來源字串中是安全的、在除錯樣板中是有用的、在可以被讀者終端機模擬器重播的問題留言中則是危險的。

在上線前測試序列

即使是一個完美構成的 SGR 序列,其品質也只等同於讀取它的消費者。Linux 與 macOS 上的現代模擬器實作了基礎的 30-37 與 40-47 代碼以及 xterm 明亮延伸;較舊的終端機、像 tmux 或 screen 這類多工器、被重新導向的非互動輸出,以及遠端 shell,都可能各自改變可見的結果。ECMA-48 定義了該標準,但並未強制要求明亮調色盤;xterm 相容對應是事實上的選擇。有些應用程式遵守 NO_COLOR 慣例並完全略過 SGR;有些會偵測 Windows 虛擬終端機處理並輸出不同的代碼;有些則在 stdout 不是終端機時停用顏色。

兩個實用的檢查有助益。第一,產生你實際所需的最少參數集合 (例如只要單一前景顏色,而不是粗體加底線加明亮變體,除非每個屬性都確實必要),並驗證可見表示法的閱讀結果符合預期。第二,將原始序列貼入你的使用者實際會執行的真實終端機、主題與輸出模式,然後立即印出一個普通字元,確認尾端重設已清除作用中的呈現。重設是一道護欄,並不保證每個消費者都以相同方式解讀串流。

如果你的輸出可能會由無法解讀 SGR 的應用程式顯示,請提供一個停用顏色的方式。網頁本身沒有終端機模擬器,也無法判斷目的地是否支援 ECMA-48、xterm 延伸、Windows 虛擬終端機處理、NO_COLOR 慣例,或被重新導向的非互動輸出,因此最終的驗證必須對著真實的目的地進行,而不是對著產生器進行。

延伸閱讀:Terminal Color Codes: 16-Color SGR Lookup and Builder

延伸閱讀:Extract Code From a Docker Image as a PNG