Построение гистограммы из выходных данных команды bash

Построение гистограммы из выходных данных команды bash

У меня получился следующий результат:

2015/1/7    8
2015/1/8    49
2015/1/9    40
2015/1/10   337
2015/1/11   11
2015/1/12   3
2015/1/13   9
2015/1/14   102
2015/1/15   62
2015/1/16   10
2015/1/17   30
2015/1/18   30
2015/1/19   1
2015/1/20   3
2015/1/21   23
2015/1/22   12
2015/1/24   6
2015/1/25   3
2015/1/27   2
2015/1/28   16
2015/1/29   1
2015/2/1    12
2015/2/2    2
2015/2/3    1
2015/2/4    10
2015/2/5    13
2015/2/6    2
2015/2/9    2
2015/2/10   25
2015/2/11   1
2015/2/12   6
2015/2/13   12
2015/2/14   2
2015/2/16   8
2015/2/17   8
2015/2/20   1
2015/2/23   1
2015/2/27   1
2015/3/2    3
2015/3/3    2

И я хотел бы нарисовать гистограмму

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

Знаете ли вы, есть ли команда bash, которая позволит мне это сделать?

решение1

В perl:

perl -pe 's/ (\d+)$/"="x$1/e' file
  • eприводит к оценке выражения, поэтому я получаю =повторное использование значения $1(числа, совпадающего с (\d+)).
  • "="x($1\/3)Вместо этого можно использовать "="x$1, чтобы получить более короткие строки. (The /экранируется, поскольку мы находимся в середине команды подстановки.)

В bash(вдохновленоэтот ТАК ответ):

while read d n 
do 
    printf "%s\t%${n}s\n" "$d" = | tr ' ' '=' 
done < test.txt
  • printfдополняет вторую строку пробелами, чтобы получить ширину $n ( %${n}s), и я заменяю пробелы на =.
  • Столбцы разделяются с помощью табуляции ( \t), но вы можете сделать это более красиво, перейдя по конвейеру к column -ts'\t'.
  • $((n/3))Вместо этого можно использовать ${n}, чтобы получить более короткие строки.

Другая версия:

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

Единственный недостаток, который я вижу, это то, что вам нужно будет перенаправить sedвывод куда-то, если вы хотите уменьшить масштаб, в противном случае это самый чистый вариант. Если есть вероятность, что ваш входной файл содержит один из них, вам [?*следует привести команду с помощью set -f;.

решение2

Попробуйте это в:

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

ПОЯСНЕНИЯ:

  • -aявляется явным split()в @Fмассиве, мы получаем значения с помощью$F[n]
  • xэто сказать Perl напечатать символ N раз
  • ($F[1] / 5): здесь мы получаем число и делим его на 5 для красивого вывода (простая арифметика)

решение3

Легко сawk

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

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

Или с моим любимым языком программирования

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

решение4

Вы могли бы сделать что-то подобное сбарглагол вМиллер

$ mlr --nidx --repifs --ofs tab bar -f 2 file
2015/1/7    ***.....................................
2015/1/8    *******************.....................
2015/1/9    ****************........................
2015/1/10   ***************************************#
2015/1/11   ****....................................
2015/1/12   *.......................................
.
.
.

Связанный контент