5 use List::Util qw( min max sum );
6 use open qw( :std :utf8 );
10 use Getopt::Long '2.33', qw( :config gnu_getopt );
11 sub podexit { require Pod::Usage; Pod::Usage::pod2usage(-exitval => 0, @_) }
17 'usage|h' => sub { podexit() },
18 'help' => sub { podexit(-verbose => 2) },
19 ) or exit 64; # EX_USAGE
20 $opt{width} ||= $ENV{COLUMNS} || 80;
24 my @lines = readline or exit;
26 my @values = map { s/^\h* ( -? [0-9]* (?:\.[0-9]+)? )//x and $1 } @lines;
27 my @order = sort { $b <=> $a } grep { length } @values;
28 length > $opt{trim} + 1 and substr($_, $opt{trim}) = '…' for @lines;
30 my $maxval = $order[0];
31 my $minval = min $order[-1], 0;
32 my $lenval = max map { length } @order;
33 my $len = $opt{trim} ? $opt{trim} + 2 :
34 1 + max map { length } @lines; # left padding
35 my $size = ($maxval - $minval) &&
36 ($opt{width} - $lenval - $len) / ($maxval - $minval); # bar multiplication
39 if ($opt{markers} // 1) {
40 sub orderpos { (($order[$_[0]] + $order[$_[0] + .5]) / 2 - $minval) * $size }
41 $barmark[ (sum(@order) / @order - $minval) * $size ] = '='; # average
42 $barmark[ orderpos($#order / 2) ] = '+'; # mean
43 $barmark[ -$minval * $size ] = '|' if $minval < 0; # zero
44 defined and $opt{color} and $_ = "\e[36m$_\e[0m" for @barmark;
47 for my $nr (0 .. $#lines) {
48 my $val = $values[$nr];
50 my $color = !$opt{color} ? 0 :
51 $val == $order[0] ? 32 : # max
52 $val == $order[-1] ? 31 : # min
54 printf "\e[%sm", $color if $color;
55 printf "%*s", $lenval, $val;
56 print "\e[0m" if $color;
58 printf '%-*s', $len, $lines[$nr];
59 print $barmark[$_] // '-' for 1 .. (($val || 0) - $minval) * $size;
67 graph - append bar chart to input numbers
71 B<graph> [<options>] [<input>]
75 Each line starting with a number is given a bar to visualise relative sizes.
83 Disable colored output of values and bar markers.
85 =item -l, --length=<size>
87 Trim line contents (between number and bars)
88 to a maximum number of characters.
89 The exceeding part is replaced by an abbreviation sign.
93 Statistical positions to indicate on bars.
94 Cannot be customized yet,
95 only disabled by providing an empty argument.
97 Any value enables all marker characters:
104 the sum of all values divided by the number of counted lines.
109 the middle value or average between middle values.
113 =item -w, --width=<columns>
115 Override the maximum number of columns to use.
116 Appended graphics will extend to fill up the entire screen.
122 Commonly used after counting, such as users on the current server:
124 users | sed 's/ /\n/g' | sort | uniq -c | graph
126 Letter frequencies in text files:
128 cat /usr/share/games/fortunes/*.u8 |
129 perl -CO -nE 'say for grep length, split /\PL*/, uc' |
130 sort | uniq -c | graph
132 Memory usage of user processes:
134 ps xo %mem,pid,cmd | graph -l40
136 Sizes (in megabytes) of all root files and directories:
140 Number of HTTP requests per day:
142 cat log/access.log | cut -d\ -f4 | cut -d: -f1 | uniq -c | graph
144 Any kind of database query with leading counts:
146 echo 'SELECT count(*),schemaname FROM pg_tables GROUP BY 2' |
149 Git statistics, such commit count by year:
151 git log --pretty=%ci | cut -b-4 | uniq -c | graph
153 Or the most frequent authors:
155 git shortlog -sn | graph | head -3
159 Mischa POSLAWSKY <perl@shiar.org>