grepの色の仕組み

続きです。
grepのprint_line_middleを読んでみます。

takk@deb9:~/src/grep-2.27/src$ cat -n grep.c | sed -ne '1151,1217p'
  1151  static char *
  1152  print_line_middle (char *beg, char *lim,
  1153                     const char *line_color, const char *match_color)
  1154  {
  1155    size_t match_size;
  1156    size_t match_offset;
  1157    char *cur;
  1158    char *mid = NULL;
  1159    char *b;
  1160
  1161    for (cur = beg;
  1162         (cur < lim
  1163          && ((match_offset = execute (beg, lim - beg, &match_size, cur))
  1164              != (size_t) -1));
  1165         cur = b + match_size)
  1166      {
  1167        b = beg + match_offset;
  1168
  1169        /* Avoid matching the empty line at the end of the buffer. */
  1170        if (b == lim)
  1171          break;
  1172
  1173        /* Avoid hanging on grep --color "" foo */
  1174        if (match_size == 0)
  1175          {
  1176            /* Make minimal progress; there may be further non-empty matches.  */
  1177            /* XXX - Could really advance by one whole multi-octet character.  */
  1178            match_size = 1;
  1179            if (!mid)
  1180              mid = cur;
  1181          }
  1182        else
  1183          {
  1184            /* This function is called on a matching line only,
  1185               but is it selected or rejected/context?  */
  1186            if (only_matching)
  1187              {
  1188                char sep = out_invert ? SEP_CHAR_REJECTED : SEP_CHAR_SELECTED;
  1189                if (! print_line_head (b, match_size, lim, sep))
  1190                  return NULL;
  1191              }
  1192            else
  1193              {
  1194                pr_sgr_start (line_color);
  1195                if (mid)
  1196                  {
  1197                    cur = mid;
  1198                    mid = NULL;
  1199                  }
  1200                fwrite_errno (cur, 1, b - cur);
  1201              }
  1202
  1203            pr_sgr_start_if (match_color);
  1204            fwrite_errno (b, 1, match_size);
  1205            pr_sgr_end_if (match_color);
  1206            if (only_matching)
  1207              putchar_errno (eolbyte);
  1208          }
  1209      }
  1210
  1211    if (only_matching)
  1212      cur = lim;
  1213    else if (mid)
  1214      cur = mid;
  1215
  1216    return cur;
  1217  }
takk@deb9:~/src/grep-2.27/src$

前回のgrep時にも見つけた関数ですが、1203行目のpr_sgr_start_if、1206行目のpr_sgr_end_ifが色制御に関連してそうです。
それぞれ関数を確認してみます。

 311 /* SGR utility functions.  */
 312 static void
 313 pr_sgr_start (char const *s)
 314 {
 315   if (*s)
 316     print_start_colorize (sgr_start, s);
 317 }
 318 static void
 319 pr_sgr_end (char const *s)
 320 {
 321   if (*s)
 322     print_end_colorize (sgr_end);
 323 }

sgr_startという引数と、s、つまりmatch_colorを渡している関数print_start_colorizeを読んでます。sgr_startが気になります。

すぐ上の行にありました。

 308 static const char *sgr_start = "\33[%sm\33[K";
 309 static const char *sgr_end   = "\33[m\33[K";

色つけのエスケープシーケンスですね。%sを使ってるところから、printfに渡す文字列かと思います。ということは、print_start_colorizeの正体は、printfですね。まあ、間違ってたとしても、困ることはないので、わざわざ見なくてもよいでしょう。

ということで、grep –colorで表示される色は、ただのエスケープシーケンスですね。

では何故、パイプで渡すと色が消えるのか。。。

つづく

Leave a Reply

Your email address will not be published. Required fields are marked *

CAPTCHA