从 bash 命令输出中绘制直方图

Nat*_*tim 34 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
Run Code Online (Sandbox Code Playgroud)

我想画一个直方图

2015/1/7  ===
2015/1/8  ===========
2015/1/9  ==========
2015/1/10 ====================================================================
2015/1/11 ===
2015/1/11 =
...
Run Code Online (Sandbox Code Playgroud)

你知道是否有一个 bash 命令可以让我这样做吗?

mur*_*uru 15

perl

perl -pe 's/ (\d+)$/"="x$1/e' file
Run Code Online (Sandbox Code Playgroud)
  • e导致表达式被评估,所以我=重复使用$1(匹配的数字(\d+))的值。
  • 你可以做"="x($1\/3)而不是"="x$1得到更短的线。(/因为我们正处于替换命令的中间,所以被转义了。)

bash(灵感来自这个 SO answer):

while read d n 
do 
    printf "%s\t%${n}s\n" "$d" = | tr ' ' '=' 
done < test.txt
Run Code Online (Sandbox Code Playgroud)
  • printf使用空格填充第二个字符串以获得$n ( %${n}s)的宽度,然后我将空格替换为=.
  • 列使用制表符 ( \t)分隔,但您可以通过管道连接到column -ts'\t'.
  • 您可以使用$((n/3))而不是${n}获得更短的行。

另一个版本:

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

我能看到的唯一缺点是,sed如果您想缩小规模,您需要将的输出通过管道传输到某些内容,否则这是最干净的选择。如果您的输入文件有可能包含您中的一个,则[?*应该使用 w/ 引导命令set -f;

  • Bravo 也展示了一个 shell 解决方案。您的 Perl 解决方案也非常干净。 (2认同)

Gil*_*not 14

试试这个:

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

说明:

  • -a是一个明确split()@F阵列,我们得到的价值观$F[n]
  • x 是告诉 perl 打印一个字符 N 次
  • ($F[1] / 5) :在这里我们得到数字并将其除以 5 以获得漂亮的打印输出(简单的算术)


iru*_*var 9

轻松搭配 awk

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

2015/1/7 ========
2015/1/8 =================================================
2015/1/9 ========================================
..
..
Run Code Online (Sandbox Code Playgroud)

或者用我最喜欢的编程语言

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


ste*_*ver 9

你可以用Miller中的酒吧动词做类似的事情

$ 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   *.......................................
.
.
.
Run Code Online (Sandbox Code Playgroud)

  • 您能再解释一下每个参数的作用吗?即使阅读[参考](http://johnkerl.org/miller/doc/reference.html)我也不清楚 (2认同)

小智 8

怎么样:

#! /bin/bash
histo="======================================================================+"

read datewd value

while [ -n "$datewd" ] ; do
   # Use a default width of 70 for the histogram
   echo -n "$datewd      "
   echo ${histo:0:$value}

   read datewd value
done
Run Code Online (Sandbox Code Playgroud)

其中产生:

~/bash $./histogram.sh < histdata.txt
2015/1/7    ========
2015/1/8    =================================================
2015/1/9    ========================================
2015/1/10   ======================================================================+
2015/1/11   ===========
2015/1/12   ===
2015/1/13   =========
2015/1/14   ======================================================================+
2015/1/15   ==============================================================
2015/1/16   ==========
2015/1/17   ==============================
2015/1/18   ==============================
2015/1/19   =
2015/1/20   ===
2015/1/21   =======================
2015/1/22   ============
2015/1/24   ======
2015/1/25   ===
2015/1/27   ==
2015/1/28   ================
2015/1/29   =
2015/2/1    ============
2015/2/2    ==
2015/2/3    =
2015/2/4    ==========
2015/2/5    =============
2015/2/6    ==
2015/2/9    ==
2015/2/10   =========================
2015/2/11   =
2015/2/12   ======
2015/2/13   ============
2015/2/14   ==
2015/2/16   ========
2015/2/17   ========
2015/2/20   =
2015/2/23   =
2015/2/27   =
2015/3/2    ===
2015/3/3    ==
~/bash $
Run Code Online (Sandbox Code Playgroud)


JJo*_*oao 8

(这不完全是你问的,但是)使用 Gnuplot,如果你在 X 中,请尝试:

gnuplot -p -e 'set sty d hist;set xtic rot; plot "file" u 2:xtic(1)'
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

  • @mh-cbon,gnuplot 可以做很多不同的事情(请参阅他们的文档和演示)。stdin `seq 30 | 的示例 gnuplot -p -e '设置样式 d hi​​st; 绘制“-”u($1**3)`。您还可以使用“/dev/stdin” (2认同)