grepの色を伝えたい


アニメ『色づく世界の明日から』

きれいですねえ。色がきれい。いろんな色が見える世界は美しいです

前回は、grepコマンドの前に色指定するGREP_COLORを設定しましたが、exportしておけば、毎回設定する必要がなくなります。

takk@deb9:~/tmp/gmp-6.1.2+dfsg$ export GREP_COLOR='01;33'
takk@deb9:~/tmp/gmp-6.1.2+dfsg$

黄色の設定しました。

grep実行。

takk@deb9:~/tmp/gmp-6.1.2+dfsg$ grep -rn In.general --color

ところで、この色ってパイプで伝わるでしょうか。

takk@deb9:~/tmp/gmp-6.1.2+dfsg$ grep -rn In.general --color | tail -3

tailの出力時には、白に戻っています。
ん~、tail後も同じ色で表示することはできないものでしょうか。世界に色を付けたいです。

ということで、そもそもgrepは色表示をどうしているかってところから始めたいと思います。grepのソース取得。

takk@deb9:~/src$ apt-get source grep

lsを確認。

takk@deb9:~/src$ cd grep-2.27/
takk@deb9:~/src/grep-2.27$ ls
ABOUT-NLS       Makefile.am     THANKS.in   configure.ac   maint.mk
AUTHORS         Makefile.in     TODO        debian         po
COPYING         NEWS            aclocal.m4  dist-check.mk  src
ChangeLog       README          build-aux   doc            tests
ChangeLog-2009  README-alpha    cfg.mk      gnulib-tests   thanks-gen
GNUmakefile     README-release  config.hin  lib
INSTALL         THANKS          configure   m4
takk@deb9:~/src/grep-2.27$

grepコマンドは、grep.cでしょうね。
grep.cをgrepしてcolorを使っている箇所を数えてみます。

takk@deb9:~/src/grep-2.27$ cd src
takk@deb9:~/src/grep-2.27/src$ grep color grep.c | wc -l
111
takk@deb9:~/src/grep-2.27/src$

ちょっと多いですね。他のキーワードで探すことにします。

デフォルトの色なんかどうでしょうか。’01;31’。

takk@deb9:~/src/grep-2.27/src$ grep '01;31' grep.c
static const char *selected_match_color = "01;31";      /* bold red */
static const char *context_match_color  = "01;31";      /* bold red */
     GREP_COLORS='ms=01;31:mc=01;31:sl=:cx=:fn=35:ln=32:bn=32:se=36'
takk@deb9:~/src/grep-2.27/src$

ありましたね。
~match_colorという変数を使ってるっぽいので、これもまた検索してみます。数を先に数えてからです。

takk@deb9:~/src/grep-2.27/src$ grep match_color grep.c | wc -l
18
takk@deb9:~/src/grep-2.27/src$

18行ぐらいなら全部見ていきましょう。

takk@deb9:~/src/grep-2.27/src$ grep match_color grep.c | cat -n
     1  static const char *selected_match_color = "01;31";      /* bold red */
     2  static const char *context_match_color  = "01;31";      /* bold red */
     3    /* Our caller just set selected_match_color.  */
     4    context_match_color = selected_match_color;
     5      { "mt", &selected_match_color, color_cap_mt_fct }, /* both ms/mc */
     6      { "ms", &selected_match_color, NULL }, /* selected matched text */
     7      { "mc", &context_match_color,  NULL }, /* context matched text */
     8                     const char *line_color, const char *match_color)
     9            pr_sgr_start_if (match_color);
    10            pr_sgr_end_if (match_color);
    11    const char *match_color;
    12        match_color = (sep == SEP_CHAR_SELECTED
    13                       ? selected_match_color : context_match_color);
    14      line_color = match_color = NULL; /* Shouldn't be used.  */
    15        || (color_option && (*line_color || *match_color)))
    16        if (matching && (only_matching || *match_color))
    17            beg = print_line_middle (beg, lim, line_color, match_color);
    18          selected_match_color = context_match_color = userval;
takk@deb9:~/src/grep-2.27/src$

9,10行目は、関数名にstartとendという言葉が入っていて、しかも引数にmatch_colorを指定しているので、色指定開始と終了って感じでしょうか。
あと、17行目は、print_lineなので、行の表示の関数ですが、_middleとあるので、中間、つまりヒットしている文字列の表示でしょうか。しかし引数にmatch_colorとline_colorが混在しているので、単純にファイル名や行番号を抜いたヘッダ部分を除いた行の表示かもしれません。
print_lineでさらに検索してみます。
役割的に、この名前がつく関数がたくさんあることはないと思いますので、wc -lは確認しません。

takk@deb9:~/src/grep-2.27/src$ grep print_line grep.c
print_line_head (char *beg, size_t len, char const *lim, char sep)
print_line_middle (char *beg, char *lim,
              if (! print_line_head (b, match_size, lim, sep))
print_line_tail (char *beg, const char *lim, const char *line_color)
    if (! print_line_head (beg, lim - beg - 1, lim, sep))
          beg = print_line_middle (beg, lim, line_color, match_color);
          beg = print_line_tail (beg, lim, line_color);
takk@deb9:~/src/grep-2.27/src$

print_lineに、headがあるのは想定してましたが、tailもありました。
print_line_tailは、引数にmatch_colorを含んでいないので、やはりprint_line_middleでヒットした色を出しているんだと思います。

つづく

Leave a Reply

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

CAPTCHA