flw 的工具箱

实用的 group by 工具

本文发表于 25 Jul 2014

在 Linux 下工作的许多朋友们应该都用过类似于下面这样的命令组合:

  cat FILE | grep PATTERN | awk '{print $5}' | sort | uniq -c | sort -nk1 | tail -10

这条命令是一个展示 Unix 管道功能的绝佳的例子,它依次做了下面几件事:

  1. 读取输入(比如从文件 FILE)
  2. 从中过滤一些感兴趣的记录
  3. 然后挑选这些记录中有用的字段
  4. 对它们进行分组计数
  5. 对计数的结果进行排序,并取其中 10 个较大者

学过 SQL 的朋友们很快会发现它其实和一条 SQL 语句差不多:

  select FIELD_5, COUNT(*) from FILE where PATTERN group by FIELD_5 sort by FIELD_5 limit 10

从笔者的实际观察来看,Linux 用户可以分为三类:

所以如果能够发明一条命令来代替上面的一串命令的话,应该对第一类和第二类用户来说应该会更方便一些。 也许第三类用户可能会觉得不是很有必要,那么请允许我多说几句。

实际工作中遇到的情况可能会比上面的例子更复杂一些:

有鉴于此,我之前曾经设计了一个叫做 gb 的工具,它可以有效地简化上面的过程。 它的一个不完全实现的版本已经帮助了许许多多的人,而现在我决定对它做一些增强。

首先请看一下我之前的一篇设计文档(实际上是一个帮助):

Usage:

  gb [OPTION]...

gb(means Group By) is a tool which very very like the SELECT statement of SQL language. please take a look first:

  select count(*), sum(FIELD_5) from FILE where PATTERN group by FIELD_4 limit 10

VS

  tselect --count ---sum 5 --from ufile --where pattern --group-by 4 --limit 10

or more simply:

  tselect -c -s5 ufile -w pattern -g4 -l10

as you known, most options can be writen as just first character.

following options are available:

-h, --help                : display this help and exit.
-v, --version             : output version information and exit.

-f, --from FILE1,FILE2    : FROM clause, if not provided or provided as `-',
                            read from standard input. option name `--from/-f' is
                            optional, bare-filename is acceptable also.

-g, --group-by LIST       : GROUP BY what fields? default to 1. You can use -g0 to
                            group by whole line.
-F, --field-sep fs        : field separator, same as 'awk -F'.

-l, --limit N             : LIMIT clause, just output top N lines of report.
--reverse -r              : reverse output.

-k, --skip N              : skip first N lines. this is useful for skip table header
                            such as *ps/netstat*.
-w, --where PERL-REGEXP   : WHERE clause. Just focus those lines which are match 
                            PERL-REGEXP.

-c, --count               : COUNT(\*) function. print amount for each group,
                            it is optional if no --sum provided.

-u, --no-count            : only print unique fields, dont count.
-s, --sum LIST            : use SUM() to instead COUNT(). If you also need COUNT() both, 
                            please give --count option together.

--web                     : visual report!

Designed by flw, please report bugs to flw@cpan.org.

顺便备忘一下刚刚构思的几个点子: