Zeichnen eines Histogramms aus der Ausgabe eines Bash-Befehls

Zeichnen eines Histogramms aus der Ausgabe eines Bash-Befehls

Ich habe folgende Ausgabe:

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

Und ich möchte ein Histogramm zeichnen

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

Wissen Sie, ob es einen Bash-Befehl gibt, mit dem ich das tun kann?

Antwort1

In perl:

perl -pe 's/ (\d+)$/"="x$1/e' file
  • ebewirkt, dass der Ausdruck ausgewertet wird, sodass ich ihn =mit dem Wert von $1(der mit übereinstimmenden Zahl (\d+)) wiederholt bekomme.
  • Sie könnten "="x($1\/3)anstelle von verwenden "="x$1, um kürzere Zeilen zu erhalten. (Das /wird maskiert, da wir uns mitten in einem Ersetzungsbefehl befinden.)

In bash(inspiriert vondiese SO-Antwort):

while read d n 
do 
    printf "%s\t%${n}s\n" "$d" = | tr ' ' '=' 
done < test.txt
  • printffüllt die zweite Zeichenfolge mit Leerzeichen auf, um eine Breite von $n ( %${n}s) zu erhalten, und ich ersetze die Leerzeichen durch =.
  • Die Spalten werden durch einen Tabulator ( \t) abgegrenzt, Sie können es aber schöner gestalten, indem Sie eine Weiterleitung an durchführen column -ts'\t'.
  • Sie können $((n/3))anstelle von verwenden ${n}, um kürzere Zeilen zu erhalten.

Andere Version:

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

Der einzige Nachteil, den ich sehe, ist, dass Sie seddie Ausgabe von irgendwohin weiterleiten müssen, wenn Sie verkleinern möchten, ansonsten ist dies die sauberste Option. Wenn die Möglichkeit besteht, dass Ihre Eingabedatei eines davon enthält, [?*sollten Sie den Befehl mit / einleiten set -f;.

Antwort2

Versuchen Sie dies in:

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

ERKLÄRUNGEN:

  • -aist ein explizites split()In- @FArray, erhalten wir die Werte mit$F[n]
  • xbesteht darin, Perl anzuweisen, ein Zeichen N-mal zu drucken.
  • ($F[1] / 5): hier erhalten wir die Zahl und dividieren sie durch 5 für eine schöne Druckausgabe (einfache Arithmetik)

Antwort3

Einfach mitawk

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

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

Oder mit meiner Lieblingsprogrammiersprache

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

Antwort4

So etwas könnte man machen mit demBarVerb inMüller

$ 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   *.......................................
.
.
.

verwandte Informationen