保持 grep 的输出重定向到 less 时的颜色高亮

问题

使用 grep 搜索,比如:

$ cat a.txt | grep -a "word"

在输出结果里,匹配到的字符会通过颜色高亮显示,方便定位;

但如果输出结果比较多,有时还带上下文一起,就需要分屏显示,比如这样使用:

$ cat a.txt | grep -a "word"  | less -NR

这时,匹配到的字符没有了颜色高亮,即使 less 已经加上了 -R 选项也不行。

走读实现代码

浏览了 grep 源代码里的相关逻辑,主要是 color_option 变量的赋值和使用:

定义:

/* If nonzero, use color markers.  */
static int color_option;

根据命令行参数初始化:

      case COLOR_OPTION:
        if (optarg)
          {
            if (!strcasecmp (optarg, "always") || !strcasecmp (optarg, "yes")
                || !strcasecmp (optarg, "force"))
              color_option = 1;
            else if (!strcasecmp (optarg, "never") || !strcasecmp (optarg, "no")
                     || !strcasecmp (optarg, "none"))
              color_option = 0;
            else if (!strcasecmp (optarg, "auto") || !strcasecmp (optarg, "tty")
                     || !strcasecmp (optarg, "if-tty"))
              color_option = 2;
            else
              show_help = 1;
          }
        else
          color_option = 2;
        break;

如果命令行参数里没有指定,那么进行自动判断:

  if (color_option == 2)
    color_option = possibly_tty && should_colorize () && isatty (STDOUT_FILENO);
  init_colorize ();

解决

color_option 默认的是 auto 自动判断,即在输出时,检查环境变量 TERM 以及接口 int isatty(int fd),如果结果是输出到控制台,那么就加上颜色高亮。而对于通过管道输出到 less,就没有颜色高亮了。

所以,对于这个问题,可以加上 --color=always 选项,强制要求颜色高亮,比如:

$ cat a.txt | grep -a --color=always "word"  | less -NR

这样就可以了。

Read More: