Karp 的技术博客

大家有没有注意到,在我们使用 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"

可以看到终端中将出现如下输出:

Xnip2024-03-29_23-09-53.png

文字变成红色的了!
那么上述指令时怎么控制文字的颜色的呢?
紧跟在 [ 之后数字 38 告诉终端转义序列要控制文字的前景色了,后续的 5 表示采用 256色,1 表示使用红色,随即转义序列以 m 结束,进入一般字符串部分;
在字符串的最后,又开始了一个转义序列,数字 0 表示重置所有的字体样式处理,以防止本条指令执行之后还会影响其他指令的颜色输出;

控制参数

Xnip2024-03-29_23-10-54.png

来点骚操作
ANSI转义序列对于文字样式的控制效果时可以叠加的,使用示例如下:

echo -e "\e[38;5;255;48;5;1;1;4;9;5m红底白字加粗闪烁\e[0m\e[38;5;4;1m蓝色加粗\e[0m"
输出如下:

3978608-8089066057edef36.webp

注意:上述样例中蓝色加粗部分在定义样式之前使用字符串\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程序中输出样式丰富的字符串到终端,我们需要实现一个工具类。

php

版权属于:karp
作品采用:本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。
更新于: 2024年10月18日 06:29
10

目录

来自 《【技巧】让你的PHP命令行输出丰富多彩》