美文网首页
通过转义符实现设置终端输出的颜色和显示方式

通过转义符实现设置终端输出的颜色和显示方式

作者: 单板小智 | 来源:发表于2017-04-19 17:53 被阅读0次

    我们在linux 上调试代码的时候, 往往需要往终端中输出大量的调试信息, 但是如果各个级别的调试信息文字的颜色、大小都是一样的话, 我们往往无法一眼找到比如错误日志或者其他级别的日志

    image

    图中只是简单的做了个测试, 真实环境下的调试信息, 远比配图要复杂的多, 如果在调试某个 bug 的时候, 一下子甩出一堆文字, 要定位部分输出, 还是很考究眼力。

    有没有什么方法能让调试信息一目了然呢? 当然有, 而且很简单。

    在linux终端中, 字符颜色和显示方式是由转义序列控制的, 是文本模式下的系统显示功能, 与具体开发语言并无关系(这就代表, 任何开发语言都能够使用这个方法😯)。

    转义序列

    转义序列以控制字符ESC开头, 该字符的 ASCII 码十进制表示为 27, 十六进制为 0x1B, 八进制表示为 033 。多数的转义序列超过两个字符, 所以通常以ESC和左括号[开头。该起始序列称为控制序列引导符(CSI, Control Sequence Intro), 通常由\033或者\e[代替。

    通过转义序列设置终端显示属性时, 可以采用下列格式

    \033[ Param {;Param;...} m
    

    或者是:

    \e[ Param {;Param;...}m
    

    其中, \033[\e[引导转义序列, m表示设置属性并结束转义。Param为属性值, {...} 表示参数是可以多选的, 多个参数之间用分号隔开, 不限制顺序。

    转义序列可被控制字符 CAN(Cancel) 和 SUB(Substitute)中断。

    转义序列相关常用参数

    man console_codes 可以查看更多的参数描述

    显示:

    • 0: 默认
    • 1: 粗体/高亮
    • 22: 非粗体
    • 4: 单条下滑线
    • 24: 无下滑线
    • 5: 闪烁
    • 25: 吴闪烁
    • 7: 反显、翻转前景色和背景色
    • 27: 无反显

    颜色:

    • 0: 黑
    • 1: 红
    • 2: 绿
    • 3: 黄
    • 4: 蓝
    • 5: 洋红
    • 6: 青色
    • 7: 白

    前景色为 30 + 颜色值, 如31表示前景色是红色

    背景色为 40 + 颜色值, 如41表示背景色为红色

    因此, 通过转义序列设置终端显示属性时, 常见格式为:

    \033[显示方式;前景色;背景色m输出字符串\e[显示方式;前景色;背景色m输出字符串\e[0m
    

    此外, 还有一些 ANSI 控制码, 如:

    • nA(光标上移n行)
    • nB(光标下移动n行)
    • C(光标右移动n行)
    • nD (光标左移n行 )
    • 2J(清屏)
    • K(清除从光标到行尾的内容)
    • s(保存光标位置)
    • u(恢复光标位置)
    • ?25l(隐藏光标)
    • ?25l(显示光标)
    \e[0m   # 用于恢复默认终端输出属性, 否则影响后续输出。
    

    php 中实现

    先把常用的属性定义为常量, 方便后续调用:

    <?php
    /**
     * Created by PhpStorm.
     * User: collin
     * Date: 2017/4/17
     * Time: 下午3:45
     */
    class Log {
      const DEBUG = 1;
    
      // 颜色
      private const NONE = "\e[0m";
      private const BLACK = "\e[0;30m";
      private const L_BLACK = "\e[1;30m";
      private const RED = "\e[0;31m";
      private const L_RED = "\e[1;31m";
      private const GREEN = "\e[0;32m";
      private const L_GREEN = "\e[1;32m";
      private const BROWN = "\e[0;33m";
      private const YELLOW = "\e[1;33m";
      private const BLUE = "\e[0;34m";
      private const L_BLUE = "\e[1;34m";
      private const PURPLE = "\e[0;35m";
      private const L_PURPLE = "\e[1;35m";
      private const CYAN = "\e[0;36m";
      private const L_CYAN = "\e[1;36m";
      private const GRAY = "\e[0;37m";
      private const WHITE = "\e[1;37m";
    
      // 字体
      private const BOLD = "\e[1m";
      private const UNDERLINE = "\e[4m";
      private const BLINK = "\e[5m";
      private const REVERSE = "\e[7m";
      private const HIDE = "\e[8m";
      private const CLEAR = "\e[2J";
      private const CLRLINE = "\r\e[K\" //or \"\e[1K\r";
    
      /**
       * 控制台输出 success 级别消息
       * @param $str 日志内容
       */
      static public function console_success($str) {
        echo self::GREEN . 'SUCCESS['. date('Y-m-d H:i:s', time()).']: ' . $str . self::NONE . PHP_EOL;
      }
    
      /**
       * 控制台输出 error 级别消息
       * @param $str 日志内容
       */
      static public function console_error($str) {
        echo self::RED . 'ERROR['. date('Y-m-d H:i:s', time()).']: ' . $str . PHP_EOL;
        $arr = debug_backtrace();
        echo self::format($arr);
        echo self::NONE . PHP_EOL;
      }
    
      /**
       * 控制台输出 warning 级别消息
       * @param $str 日志内容
       */
      static public function console_warning($str) {
        echo self::BROWN . 'WARNING['. date('Y-m-d H:i:s', time()).']: ' . $str . PHP_EOL;
    
        $arr = debug_backtrace();
        echo self::format($arr);
        echo self::NONE . PHP_EOL;
      }
    
      /**
       * 如果DEBUG = 1, 则输出 debug 级别消息
       * @param $str 日志内容
       */
      static public function console_debug($str) {
        if (self::DEBUG) {
          echo self::CYAN . 'DEBUG['. date('Y-m-d H:i:s', time()).']: ' . $str . PHP_EOL;
    
          $arr = debug_backtrace();
          echo self::format($arr);
          echo self::NONE . PHP_EOL;
        }
      }
    
      /**
       * 如果 DEBUG = 1, 则遍历对象
       * @param $arr object/array
       */
      static public function console_dump_debug($arr) {
        if (self::DEBUG) {
          echo self::CYAN . 'DEBUG dump['. date('Y-m-d H:i:s', time()).']: '. PHP_EOL;
          var_dump($arr);
          echo self::NONE . PHP_EOL;
        }
      }
    
      /**
       * 控制台输出 info 级别消息
       * @param $str 日志内容
       */
      static public function console_info($str) {
        echo self::UNDERLINE . 'INFO['. date('Y-m-d H:i:s', time()).']: ' . $str . self::NONE . PHP_EOL;
      }
    
      /**
       * 格式化堆栈信息
       * @param $arr
       * @return string
       */
      static private function format($arr) {
        $str = '';
        foreach ($arr as $k => $v) {
          $file = $v['file'];
          $line = $v['line'];
          $class = isset($v['class']) ? $v['class'] . '\\' : 'stdClass\\';
          $function = $v['function'] ?? '';
          $str .= "#$k  $file($line): {$class}{$function}" . PHP_EOL;
        }
        return $str;
      }
    }
    

    上面的代码是我简单写的一个带色彩的日志类。

    相关文章

      网友评论

          本文标题:通过转义符实现设置终端输出的颜色和显示方式

          本文链接:https://www.haomeiwen.com/subject/nlyhzttx.html