大家有沒有注意到寸爆,在我們使用 composer
進行依賴管理的時候礁鲁,它在命令行中的輸出竟然是彩色的,而我們自己寫的程序使用 echo
進行輸出的時候赁豆,都是默認的黑底白字(依賴于主題)仅醇,逼格一點都不高!
探究開始
為了探究命令行帶顏色輸出魔种,我查看了安裝 composer
時從官方下載的 composer-setup.php
析二,其中的字符輸出函數(shù)如下:
/**
* colorize output
*/
function out($text, $color = null, $newLine = true)
{
$styles = array(
'success' => "\033[0;32m%s\033[0m",
'error' => "\033[31;31m%s\033[0m",
'info' => "\033[33;33m%s\033[0m"
);
$format = '%s';
if (isset($styles[$color]) && USE_ANSI) {
$format = $styles[$color];
}
if ($newLine) {
$format .= PHP_EOL;
}
printf($format, $text);
}
可以看到,這個函數(shù)中定義了三種類型的色彩輸出节预,而且都是用形如 \033[Xm
的特殊字符串將其包裝之后進行的輸出叶摄,所以,這個形式的特殊字符串究竟是個什么神奇東西安拟?
ANSI轉(zhuǎn)義序列
經(jīng)過查詢資料蛤吓,發(fā)現(xiàn)上一節(jié)中所述的神奇字符串是 ANSI轉(zhuǎn)義序列[1] ,通過它可以控制文字在終端上的樣式去扣,如加粗柱衔、斜體、顏色等愉棱。
ANSI轉(zhuǎn)義序列的解析在終端進行唆铐,不同的終端的對其的支持程度也不盡相同,本文采用的終端是 xShell
奔滑,已經(jīng)可以支持大部分的轉(zhuǎn)移序列艾岂。
序列寫法
ANSI轉(zhuǎn)義序列以 ESC轉(zhuǎn)義字符(ASCII碼為27)
和 字符[
開始,以字符 m
結(jié)束朋其,上一節(jié)代碼中的 ESC轉(zhuǎn)移字符串
采用了八進制的寫法王浴,在實際使用中我們也可以用 \e
這樣的轉(zhuǎn)義寫法脆炎。
牛刀小試
在終端執(zhí)行如下命令:
echo -e "\e[38;5;1m紅色\e[0m"
可以看到終端中將出現(xiàn)如下輸出:
文字變成紅色的了!
那么上述指令時怎么控制文字的顏色的呢氓辣?
緊跟在
[
之后數(shù)字 38
告訴終端轉(zhuǎn)義序列要控制文字的前景色了秒裕,后續(xù)的 5
表示采用 256色,1
表示使用紅色钞啸,隨即轉(zhuǎn)義序列以 m
結(jié)束几蜻,進入一般字符串部分;在字符串的最后体斩,又開始了一個轉(zhuǎn)義序列梭稚,數(shù)字
0
表示重置所有的字體樣式處理,以防止本條指令執(zhí)行之后還會影響其他指令的顏色輸出絮吵;
控制參數(shù)
下面是從 維基百科ANSI轉(zhuǎn)義序列詞條頁 所摘錄的轉(zhuǎn)義序列控制參數(shù)表:
代碼 | 作用 | 備注 |
---|---|---|
0 | 重置/正常 | 關(guān)閉所有屬性弧烤。 |
1 | 粗體或增加強度 | |
2 | 弱化(降低強度) | 未廣泛支持。 |
3 | 斜體 | 未廣泛支持蹬敲。有時視為反相顯示暇昂。 |
4 | 下劃線 | |
5 | 緩慢閃爍 | 低于每分鐘150次。 |
6 | 快速閃爍 | MS-DOS ANSI.SYS粱栖;每分鐘150以上话浇;未廣泛支持。 |
7 | 反顯 | 前景色與背景色交換闹究。 |
8 | 隱藏 | 未廣泛支持幔崖。 |
9 | 劃除 | 字符清晰,但標記為刪除渣淤。未廣泛支持赏寇。 |
10 | 主要(默認)字體 | |
11–19 | 替代字體 | 選擇替代字體 n - 1
|
20 | 尖角體 | 幾乎無支持。 |
21 | 關(guān)閉粗體或雙下劃線 | 關(guān)閉粗體未廣泛支持价认;雙下劃線幾乎無支持嗅定。 |
22 | 正常顏色或強度 | 不強不弱。 |
23 | 非斜體用踩、非尖角體 | |
24 | 關(guān)閉下劃線 | 去掉單雙下劃線渠退。 |
25 | 關(guān)閉閃爍 | |
27 | 關(guān)閉反顯 | |
28 | 關(guān)閉隱藏 | |
29 | 關(guān)閉劃除 | |
30–37 | 設(shè)置前景色 | 參見下面的顏色表。 |
38 | 設(shè)置前景色 | 下一個參數(shù)是5;n 或2;r;g;b 脐彩,見下碎乃。 |
39 | 默認前景色 | 由具體實現(xiàn)定義(按照標準)。 |
40–47 | 設(shè)置背景色 | 參見下面的顏色表惠奸。 |
48 | 設(shè)置背景色 | 下一個參數(shù)是5;n 或2;r;g;b 梅誓,見下。 |
49 | 默認背景色 | 由具體實現(xiàn)定義(按照標準)。 |
51 | Framed | |
52 | Encircled | |
53 | 上劃線 | |
54 | Not framed or encircled | |
55 | 關(guān)閉上劃線 | |
60 | 表意文字下劃線或右邊線 | 幾乎無支持梗掰。 |
61 | 表意文字雙下劃線或雙右邊線 | 幾乎無支持嵌言。 |
62 | 表意文字上劃線或左邊線 | 幾乎無支持。 |
63 | 表意文字雙上劃線或雙左邊線 | 幾乎無支持及穗。 |
64 | 表意文字著重標志 | 幾乎無支持摧茴。 |
65 | 表意文字屬性關(guān)閉 | 重置60 –64 的所有效果。 |
90–97 | 設(shè)置明亮的前景色 | aixterm(非標準)拥坛。 |
100–107 | 設(shè)置明亮的背景色 | aixterm(非標準)蓬蝶。 |
來點騷操作
ANSI轉(zhuǎn)義序列對于文字樣式的控制效果時可以疊加的,使用示例如下:
echo -e "\e[38;5;255;48;5;1;1;4;9;5m紅底白字加粗閃爍\e[0m\e[38;5;4;1m藍色加粗\e[0m"
輸出如下:
注意:上述樣例中藍色加粗部分在定義樣式之前使用字符串
\e[0m
清除了之前所配置的樣式猜惋,如果不執(zhí)行這一步,藍色加粗部分字體還會攜帶紅色背景和閃爍效果培愁。
在PHP中運用
可以觀察到上我們在上一節(jié)中我們所使用的 echo
指令都帶上了 -e
參數(shù)來進行特殊字符處理著摔,那么PHP中要怎么使用ANSI轉(zhuǎn)義序列呢?
經(jīng)過本人的親測定续,PHP中的語法接口 echo
是會進行特殊字符處理的谍咆,所以上述樣例在PHP代碼中可以這么寫:
<?php
echo "\e[38;5;255;48;5;1;1;4;9;5m紅底白字加粗閃爍\e[0m\e[38;5;4;1m藍色加粗\e[0m", PHP_EOL;
腳本的運行結(jié)果同上面截圖中的一致。
工具化
每次調(diào)整文字的樣式都要寫那么一串轉(zhuǎn)義序列太麻煩了私股,而且可讀性也很差摹察。
為了更方便地在PHP程序中輸出樣式豐富的字符串到終端,我們需要實現(xiàn)一個工具類倡鲸。