大家有没有注意到,在我们使用 composer
进行依赖管理的时候,它在命令行中的输出竟然是彩色的,而我们自己写的程序使用 echo
进行输出的时候,都是默认的黑底白字(依赖于主题),逼格一点都不高!
探究开始
为了探究命令行带颜色输出,我查看了安装 composer
时从官方下载的 composer-setup.php
,其中的字符输出函数如下:
/**
* 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);
}
可以看到,这个函数中定义了三种类型的色彩输出,而且都是用形如 \033[Xm
的特殊字符串将其包装之后进行的输出,所以,这个形式的特殊字符串究竟是个什么神奇东西?
ANSI转义序列
经过查询资料,发现上一节中所述的神奇字符串是 ANSI转义序列[1] ,通过它可以控制文字在终端上的样式,如加粗、斜体、颜色等。
ANSI转义序列的解析在终端进行,不同的终端的对其的支持程度也不尽相同,本文采用的终端是 xShell
,已经可以支持大部分的转移序列。
序列写法
ANSI转义序列以 ESC转义字符(ASCII码为27)
和 字符[
开始,以字符 m
结束,上一节代码中的 ESC转移字符串
采用了八进制的写法,在实际使用中我们也可以用 \e
这样的转义写法。
牛刀小试
在终端执行如下命令:
echo -e "\e[38;5;1m红色\e[0m"
可以看到终端中将出现如下输出:
文字变成红色的了!
那么上述指令时怎么控制文字的颜色的呢?
紧跟在
[
之后数字 38
告诉终端转义序列要控制文字的前景色了,后续的 5
表示采用 256色,1
表示使用红色,随即转义序列以 m
结束,进入一般字符串部分;在字符串的最后,又开始了一个转义序列,数字
0
表示重置所有的字体样式处理,以防止本条指令执行之后还会影响其他指令的颜色输出;
控制参数
下面是从 维基百科ANSI转义序列词条页 所摘录的转义序列控制参数表:
代码 | 作用 | 备注 |
---|---|---|
0 | 重置/正常 | 关闭所有属性。 |
1 | 粗体或增加强度 | |
2 | 弱化(降低强度) | 未广泛支持。 |
3 | 斜体 | 未广泛支持。有时视为反相显示。 |
4 | 下划线 | |
5 | 缓慢闪烁 | 低于每分钟150次。 |
6 | 快速闪烁 | MS-DOS ANSI.SYS;每分钟150以上;未广泛支持。 |
7 | 反显 | 前景色与背景色交换。 |
8 | 隐藏 | 未广泛支持。 |
9 | 划除 | 字符清晰,但标记为删除。未广泛支持。 |
10 | 主要(默认)字体 | |
11–19 | 替代字体 | 选择替代字体 n - 1
|
20 | 尖角体 | 几乎无支持。 |
21 | 关闭粗体或双下划线 | 关闭粗体未广泛支持;双下划线几乎无支持。 |
22 | 正常颜色或强度 | 不强不弱。 |
23 | 非斜体、非尖角体 | |
24 | 关闭下划线 | 去掉单双下划线。 |
25 | 关闭闪烁 | |
27 | 关闭反显 | |
28 | 关闭隐藏 | |
29 | 关闭划除 | |
30–37 | 设置前景色 | 参见下面的颜色表。 |
38 | 设置前景色 | 下一个参数是5;n 或2;r;g;b ,见下。 |
39 | 默认前景色 | 由具体实现定义(按照标准)。 |
40–47 | 设置背景色 | 参见下面的颜色表。 |
48 | 设置背景色 | 下一个参数是5;n 或2;r;g;b ,见下。 |
49 | 默认背景色 | 由具体实现定义(按照标准)。 |
51 | Framed | |
52 | Encircled | |
53 | 上划线 | |
54 | Not framed or encircled | |
55 | 关闭上划线 | |
60 | 表意文字下划线或右边线 | 几乎无支持。 |
61 | 表意文字双下划线或双右边线 | 几乎无支持。 |
62 | 表意文字上划线或左边线 | 几乎无支持。 |
63 | 表意文字双上划线或双左边线 | 几乎无支持。 |
64 | 表意文字着重标志 | 几乎无支持。 |
65 | 表意文字属性关闭 | 重置60 –64 的所有效果。 |
90–97 | 设置明亮的前景色 | aixterm(非标准)。 |
100–107 | 设置明亮的背景色 | aixterm(非标准)。 |
来点骚操作
ANSI转义序列对于文字样式的控制效果时可以叠加的,使用示例如下:
echo -e "\e[38;5;255;48;5;1;1;4;9;5m红底白字加粗闪烁\e[0m\e[38;5;4;1m蓝色加粗\e[0m"
输出如下:
注意:上述样例中蓝色加粗部分在定义样式之前使用字符串
\e[0m
清除了之前所配置的样式,如果不执行这一步,蓝色加粗部分字体还会携带红色背景和闪烁效果。
在PHP中运用
可以观察到上我们在上一节中我们所使用的 echo
指令都带上了 -e
参数来进行特殊字符处理,那么PHP中要怎么使用ANSI转义序列呢?
经过本人的亲测,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;
脚本的运行结果同上面截图中的一致。
工具化
每次调整文字的样式都要写那么一串转义序列太麻烦了,而且可读性也很差。
为了更方便地在PHP程序中输出样式丰富的字符串到终端,我们需要实现一个工具类。