Drawing a histogram from a bash command output

Try this in perl :

perl -lane 'print $F[0], "\t", "=" x ($F[1] / 5)' file

EXPLANATIONS:

  • -a is an explicit split() in @F array, we get the values with $F[n]
  • x is to tell perl to print a character N times
  • ($F[1] / 5) : here we get the number and divide it by 5 for a pretty print output (simple arithmetic)

In perl:

perl -pe 's/ (\d+)$/"="x$1/e' file
  • e causes the expression to be evaluated, so I get = repeated using the value of $1 (the number matched by (\d+)).
  • You could do "="x($1\/3) instead of "="x$1 to get shorter lines. (The / is escaped since we're in the middle of a substitution command.)

In bash (inspired from this SO answer):

while read d n 
do 
    printf "%s\t%${n}s\n" "$d" = | tr ' ' '=' 
done < test.txt
  • printf pads the second string using spaces to get a width of $n (%${n}s), and I replace the spaces with =.
  • The columns are delimited using a tab (\t), but you can make it prettier by piping to column -ts'\t'.
  • You could use $((n/3)) instead of ${n} to get shorter lines.

Another version:

unset IFS; printf "%s\t%*s\n" $(sed 's/$/ =/' test.txt) | tr ' ' =

The only drawback I can see is that you'll need to pipe sed's output to something if you want to scale down, otherwise this is the cleanest option. If there is a chance of your input file containing one of [?* you should lead the command w/ set -f;.


Easy with awk

awk '{$2=sprintf("%-*s", $2, ""); gsub(" ", "=", $2); printf("%-10s%s\n", $1, $2)}' file

2015/1/7 ========
2015/1/8 =================================================
2015/1/9 ========================================
..
..

Or with my favourite programming language

python3 -c 'import sys
for line in sys.stdin:
  data, width = line.split()
  print("{:<10}{:=<{width}}".format(data, "", width=width))' <file

Tags:

Bash