日常工作中,我们经常要在linux环境下开发程序,并输出到控制端进行调试或者结果查看,如何更美观地输出结果?
我们编写开源项目时,程序在执行过程中可能要输出编译进度,如何更容易地输出进度?
线上产品维护时,我们会经常查阅、分析、监控日志,那么又如何更清晰地输出日志?

本篇文章会重点围绕,如何在linux终端输出特效,包括文字颜色、高亮、背景色、进度条等。

  • AnsiEscapeCodes
  • 首先我们要了解下什么是AnsiEscapeCodes,大致意思是ANSI控制码,主要负责终端的输出效果。具体细节,也可以参照googlecode详细介绍AnsiEscapeCodes

    ANSI控制码均以 Esc[ 作为控制码的开始标志,其中,Esc 的ansi码为 27-十进制,33-八进制,所以在程序中,可以用 \033 表示。

    在开始符之后,紧跟着具体的控制码对应值,当要同时使用多个控制码时,可以使用连续多个Esc[进行多层渲染,也可以使用分号将多个控制符连接,具体形式如下:

    \033[控制符A
    \033[控制符A\033[控制符B\033[控制符C
    \033[控制符A;B;C

    如果渲染结束,需要声明已结束,否则后面的所有输出都会被渲染成当前的效果。而声明结束也和声明其它效果一样,只需要将控制符设置成0m(代表关闭所有属性的意思)即可:

    #使用A特效
    \033[控制符A你想要输出的内容\033[0m
    #同时使用ABC特效
    \033[控制符A\033[控制符B\033[控制符C你想要输出的内容\033[0m
    #另一种写法,同时使用ABC特效
    \033[控制符A;B;C你想要输出的内容\033[0m
    #不过需要注意,对于控制符Nm,只保留最后一个m
    \033[1;33;45m你想要输出的内容\033[0m
  • ANSI控制码表
  • 此表格是基于ANSI X3.64 为标准的,这里主要展示和Linux相关的常用控制码,关于具体明细可以依旧可以参考googlecode详细介绍AnsiEscapeCodes

    控制码符号 含义
    0m 关闭所有属性
    1m 设置高亮度
    4m 下划线
    5m 闪烁
    7m 反显
    8m 消隐
    30m 黑色(前景色)
    31m 红色(前景色)
    32m 绿色(前景色)
    33m 黄色(前景色)
    34m 蓝色(前景色)
    35m 紫色(前景色)
    36m 深绿色(前景色)
    37m 白色(前景色)
    40m 黑色(背景色)
    41m 红色(背景色)
    42m 绿色(背景色)
    43m 黄色(背景色)
    44m 蓝色(背景色)
    45m 紫色(背景色)
    46m 深绿色(背景色)
    47m 白色(背景色)
    nA 光标上移n行
    nB 光标下移n行
    nC 光标右移n列
    nD 光标左移n列
    y;H 设置光标位置
    2J 清屏
    K 清除从光标到行尾的内容
    s 保存光标位置
    u 恢复光标位置
    ?25l 隐藏光标
    ?25h 显示光标
  • 一些示例
  • 利用python,输出一个进度条:

    import time
    for i in range(1, 11):
        time.sleep(0.3)
        progress = str(float(i) / 10 * 100) + '%'
        print 'loading ' + progress.ljust(7) + '#' * i

    通过使用\r,输出可保持在当前行,不过python的print会自动输出换行,因此需要使用stdout:

    import time
    import sys
    for i in range(1, 11):
        time.sleep(0.3)
        progress = str(float(i) / 10 * 100) + '%'
        sys.stdout.write('loading ' + progress.ljust(7) + '#' * i + '\r')
        sys.stdout.flush()
    print ''

    完善demo,输出红底白色进度并加高亮显示:

    import time
    import sys
    for i in range(1, 11):
        time.sleep(0.3)
        progress = str(float(i) / 10 * 100) + '%'
        sys.stdout.write('\033[1;37;41mloading ' + progress.ljust(7) + '#' * i + '\033[0m\r')
        sys.stdout.flush()
    print ''

    最终效果图如下: