staging.inyokaproject.org

Kleine Fingerübung: ANSI-Farbtafel als Shellskript

Status: Ungelöst | Ubuntu-Version: Xubuntu 22.04 (Jammy Jellyfish)
Antworten |

juribel

Anmeldungsdatum:
20. April 2014

Beiträge: 856

Moin,

vor einiger Zeit hatte ich mir mal ein Perl-Skript geschrieben, um im Terminal eine Farbtafel anzuzeigen. Jetzt wollte ich das mal in bash ausprobieren, hier das Ergebnis.

Die Farben habe ich in zwei Loops definiert, einmal als Array (erste Variante in Zeile 4), und einmal als 256 einzelne durchnummerierte Variablen (zweite Variante in Zeile 5). Im Verlauf des Skripts benutze ich zur Farbdarstellung beide Varianten. Um die Farbcodes auszugeben, kann man z. B. printf "${fg190}", aber auch printf "${fg[190]}" (wie stellt man hier denn bloss eckige Klammern dar !?) sagen. In der Schleife werden die einzelnen durchnummerierten Hintergrundfarben mit der Array-Variante angesprochen, da eine Angabe wie printf "${fg{$i}}" zu einem Fehler "Falsche Substitution" führt. Die in den weiteren Loops verwendeten Schriftfarben (hier nur Schwarz und Weiss) lassen sich in der Variablen-Variante ansprechen.

Die vielen einzelnen Schleifen waren notwendig, weil manche Ausgaben in schwarzer und andere in weisser Schrift ausgegeben werden müssen, und es sind ja auch passende Zeilenumbrüche nötig.

Natürlich könnte ich auch konsequent nur die Array-Variante verwenden, aber in anderen Skripten, die einfach nur irgendwelchen farbigen Text ausgeben wollen wie die Ausgabe der Überschrift in Zeile 7, ist die Variablen-Variante schöner zu schreiben und zu lesen, weil man die eckigen Klammern nicht braucht.

$RES setzt alle Attribute zurück, und $CLS leert den Bildschirm.

Nicht so schön gelöst, funktioniert aber. Vielleicht hat ja jemand eine bessere Idee. Und vielleicht hat ja jemand Verwendung dafür.

Viele freundliche Grüsse, juribel

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#!/bin/bash

  RES="\e[0m"; CLS=`clear`;
  for i in {0..255}; do bg[$i]="\e[48;5;${i}m"; fg[$i]="\e[38;5;${i}m"; done
  for i in {0..255}; do eval "bg$i=\"\e[48;5;${i}m\"; fg$i=\"\e[38;5;${i}m\""; done

  printf "$CLS\n${fg226}${bg19}    Kleine Fingerübung mit 8 Bit ANSI-Farben    $RES\n\n"

  for i in {0..7}; do printf "${bg[$i]}${fg15}%4s  ${RES}" $i; done; echo;
  for i in {8..8}; do printf "${bg[$i]}${fg15}%4s  ${RES}" $i; done;
  for i in {9..15}; do printf "${bg[$i]}${fg0}%4s  ${RES}" $i; done; echo;
  for i in {16..21}; do printf "${bg[$i]}${fg15}%5s   ${RES}" $i; done; echo;
  for i in {22..27}; do printf "${bg[$i]}${fg15}%5s   ${RES}" $i; done; echo;
  for i in {28..33}; do printf "${bg[$i]}${fg15}%5s   ${RES}" $i; done; echo;
  for i in {34..39}; do printf "${bg[$i]}${fg0}%5s   ${RES}" $i; done; echo;
  for i in {40..45}; do printf "${bg[$i]}${fg0}%5s   ${RES}" $i; done; echo;
  for i in {46..51}; do printf "${bg[$i]}${fg0}%5s   ${RES}" $i; done; echo;
  for i in {52..57}; do printf "${bg[$i]}${fg15}%5s   ${RES}" $i; done; echo;
  for i in {58..63}; do printf "${bg[$i]}${fg15}%5s   ${RES}" $i; done; echo;
  for i in {64..69}; do printf "${bg[$i]}${fg15}%5s   ${RES}" $i; done; echo;
  for i in {70..75}; do printf "${bg[$i]}${fg0}%5s   ${RES}" $i; done; echo;
  for i in {76..81}; do printf "${bg[$i]}${fg0}%5s   ${RES}" $i; done; echo;
  for i in {82..87}; do printf "${bg[$i]}${fg0}%5s   ${RES}" $i; done; echo;
  for i in {88..93}; do printf "${bg[$i]}${fg15}%5s   ${RES}" $i; done; echo;
  for i in {94..99}; do printf "${bg[$i]}${fg15}%5s   ${RES}" $i; done; echo;
  for i in {100..105}; do printf "${bg[$i]}${fg15}%5s   ${RES}" $i; done; echo;
  for i in {106..111}; do printf "${bg[$i]}${fg0}%5s   ${RES}" $i; done; echo;
  for i in {112..117}; do printf "${bg[$i]}${fg0}%5s   ${RES}" $i; done; echo;
  for i in {118..123}; do printf "${bg[$i]}${fg0}%5s   ${RES}" $i; done; echo;
  for i in {124..129}; do printf "${bg[$i]}${fg15}%5s   ${RES}" $i; done; echo;
  for i in {130..135}; do printf "${bg[$i]}${fg15}%5s   ${RES}" $i; done; echo;
  for i in {136..141}; do printf "${bg[$i]}${fg15}%5s   ${RES}" $i; done; echo;
  for i in {142..147}; do printf "${bg[$i]}${fg0}%5s   ${RES}" $i; done; echo;
  for i in {148..153}; do printf "${bg[$i]}${fg0}%5s   ${RES}" $i; done; echo;
  for i in {154..159}; do printf "${bg[$i]}${fg0}%5s   ${RES}" $i; done; echo;
  for i in {160..165}; do printf "${bg[$i]}${fg15}%5s   ${RES}" $i; done; echo;
  for i in {166..171}; do printf "${bg[$i]}${fg15}%5s   ${RES}" $i; done; echo;
  for i in {172..177}; do printf "${bg[$i]}${fg15}%5s   ${RES}" $i; done; echo;
  for i in {178..183}; do printf "${bg[$i]}${fg0}%5s   ${RES}" $i; done; echo;
  for i in {184..189}; do printf "${bg[$i]}${fg0}%5s   ${RES}" $i; done; echo;
  for i in {190..195}; do printf "${bg[$i]}${fg0}%5s   ${RES}" $i; done; echo;
  for i in {196..201}; do printf "${bg[$i]}${fg15}%5s   ${RES}" $i; done; echo;
  for i in {202..207}; do printf "${bg[$i]}${fg15}%5s   ${RES}" $i; done; echo;
  for i in {208..213}; do printf "${bg[$i]}${fg15}%5s   ${RES}" $i; done; echo;
  for i in {214..219}; do printf "${bg[$i]}${fg0}%5s   ${RES}" $i; done; echo;
  for i in {220..225}; do printf "${bg[$i]}${fg0}%5s   ${RES}" $i; done; echo;
  for i in {226..231}; do printf "${bg[$i]}${fg0}%5s   ${RES}" $i; done; echo;
  for i in {232..237}; do printf "${bg[$i]}${fg15}%5s   ${RES}" $i; done; echo;
  for i in {238..243}; do printf "${bg[$i]}${fg15}%5s   ${RES}" $i; done; echo;
  for i in {244..249}; do printf "${bg[$i]}${fg0}%5s   ${RES}" $i; done; echo;
  for i in {250..255}; do printf "${bg[$i]}${fg0}%5s   ${RES}" $i; done; echo;

ChickenLipsRfun2eat Team-Icon

Supporter
Avatar von ChickenLipsRfun2eat

Anmeldungsdatum:
6. Dezember 2009

Beiträge: 12070

Sowas in der Art hab ich auch noch rumfliegen:

1
2
3
4
5
6
7
8
9
for x in {0..8}; do 
  for i in {30..37}; do 
    for a in {40..47}; do 
      printf '\e[%d;%d;%dm[%d;%d;%d]\e[0;37;40m ' $x $i $a $x $i $a;
    done; 
    echo; 
  done; 
done; 
echo;

juribel

(Themenstarter)

Anmeldungsdatum:
20. April 2014

Beiträge: 856

Not bad ☺ So eine verschachtelte Schleife wäre mir auch lieber gewesen, aber da muss ich noch ein bisschen grübeln.

Viele freundliche Grüsse, juribel

von.wert

Anmeldungsdatum:
23. Dezember 2020

Beiträge: 7756

BBS-Sysops hätten ihre wahre Freude an Euch gehabt. 😉 (Ich bin selbst einer gewesen zu Amiga-Zeiten.)

ChickenLipsRfun2eat Team-Icon

Supporter
Avatar von ChickenLipsRfun2eat

Anmeldungsdatum:
6. Dezember 2009

Beiträge: 12070

Ich hatte damals™ mal Spaß an sowas, ja. Zu mIRC-Zeiten auf Win 98 und ME, als die Welt noch schön einfach war.

juribel schrieb:

Not bad ☺ So eine verschachtelte Schleife wäre mir auch lieber gewesen, aber da muss ich noch ein bisschen grübeln.

Was gibt es da zu grübeln? x hat nacheinander die Werte von 0-8. Für jedes x läuft i von 30-37 und für jede x/i-Kombination läuft 40-47. Also {0,30,40}, {0,30,41},… dann {0,31,40}, {0,31,41},… {1,30,40}, …

juribel

(Themenstarter)

Anmeldungsdatum:
20. April 2014

Beiträge: 856

Oh, da gibt es viel zu grübeln. Wenn ich meine 36 for-Schleifen zu 6 for-Schleifen in einer übergeordneten for-Schleife zusammenfassen will, brauche ich eine zweite "äussere" Laufvariable, die ich jeweils zu der "inneren" hinzuaddiere. Und wie ihr seht, hapert es bei mir sehr bei der Arithmetik in Zeile 4:

1
2
3
4
5
#!/usr/bin/bash 
 
  for j in {0 35 71 107 142}; do 
    for i in {16..21}; do (($i+=$j)); printf $i; echo; done; 
  done; 

In bezug auf Substitution und Arithmetik finde ich die Shell-Programmierung... hmmm...

Sieht man ja auch an meinem ersten Beispiel, in dem ich eine Variable bg$i zwar definieren, aber nicht in einer Schleife ansprechen kann, warum auch immer. $bg200 funktioniert, aber 200 kann nicht in einer Variablen $i stehen und in $bg$i verwendet werden.

Oder vielleicht geht es ja doch, und ich komme einfach nur nicht dahinter.

Viele freundliche Grüsse, juribel

shiro

Anmeldungsdatum:
20. Juli 2020

Beiträge: 611

... hmmm...

mach mal

for j in 0 35 71 107 142; do for i in {16..21}; do k=$((i+j)); printf $k; echo; done; done; 

und den indirekten Zugriff auf zusammengesetzte Variablen funktioniert z.B. so:

$ a=100
$ bg100="Test"
$ eval echo \$bg$a
Test

Oder etwas eleganter:

$ b="bg$a"
$ echo $b
bg100
$ echo ${!b}
Test

Und der Zugriff auf Array-Elemente geht so:

$ fg[190]="huhu"
$ echo ${fg[190]}
huhu
$ i=190
$ echo ${fg[$i]}
huhu

juribel

(Themenstarter)

Anmeldungsdatum:
20. April 2014

Beiträge: 856

Super, danke!! So klappt es erstmal, und den Rest muss ich erst noch ein bisschen verdauen. ☺

Und dass man Variablen ohne $ definieren muss (war mir klar), und dass man beim Verwenden $ angeben muss (war mir auch klar), ausser in arithmetischen Ausdrücken mit doppelten Klammerpärchen. Das war mir nicht klar. Und dass man for in in {1..3}; sagt, aber for i in 1 2 3; ohne geschweifte Klammern. Sehr sehr verschroben und merkwürdig für einen, der von perl kommt...

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/bin/bash

  RES="\e[0m"; CLS=`clear`;
  for i in {0..255}; do bg[$i]="\e[48;5;${i}m"; fg[$i]="\e[38;5;${i}m"; done
  for i in {0..255}; do eval "bg$i=\"\e[48;5;${i}m\"; fg$i=\"\e[38;5;${i}m\""; done

  printf "$CLS\n${fg226}${bg19}    Kleine Fingerübung mit 8 Bit ANSI-Farben    $RES\n\n"

  for i in {0..7}; do printf "${bg[$i]}${fg15}%4s  ${RES}" $i; done; echo;
  for i in {8..8}; do printf "${bg[$i]}${fg15}%4s  ${RES}" $i; done;
  for i in {9..15}; do printf "${bg[$i]}${fg0}%4s  ${RES}" $i; done; echo;

  for j in 0 36 72 108 144 180; do
    for i in {16..21}; do k=$((i+j)); printf "${bg[$k]}${fg15}%5s   ${RES}" $k; done; echo;
    for i in {22..27}; do k=$((i+j)); printf "${bg[$k]}${fg15}%5s   ${RES}" $k; done; echo;
    for i in {28..33}; do k=$((i+j)); printf "${bg[$k]}${fg15}%5s   ${RES}" $k; done; echo;
    for i in {34..39}; do k=$((i+j)); printf "${bg[$k]}${fg0}%5s   ${RES}" $k; done; echo;
    for i in {40..45}; do k=$((i+j)); printf "${bg[$k]}${fg0}%5s   ${RES}" $k; done; echo;
    for i in {46..51}; do k=$((i+j)); printf "${bg[$k]}${fg0}%5s   ${RES}" $k; done; echo;
  done

  for i in {232..237}; do printf "${bg[$i]}${fg15}%5s   ${RES}" $i; done; echo;
  for i in {238..243}; do printf "${bg[$i]}${fg15}%5s   ${RES}" $i; done; echo;
  for i in {244..249}; do printf "${bg[$i]}${fg0}%5s   ${RES}" $i; done; echo;
  for i in {250..255}; do printf "${bg[$i]}${fg0}%5s   ${RES}" $i; done; echo;

Viele freundliche Grüsse, juribel

shiro

Anmeldungsdatum:
20. Juli 2020

Beiträge: 611

Anbei etwas verkürzt (kann aber noch weiter optimiert werden, wollte aber nur das ((var=tst>test?true:false)) Konstrukt mit einbauen).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
#!/bin/bash
RES="\e[0m"; CLS=`clear`;
for i in {0..255}; do bg[$i]="\e[48;5;${i}m"; fg[$i]="\e[38;5;${i}m"; done
printf "$CLS\n${fg[226]}${bg[19]}    Kleine Fingerübung mit 8 Bit ANSI-Farben    $RES\n\n"
for i in {0..15}; do 
 (( a=i<9?15:0 )); printf "${bg[$i]}${fg[$a]}%4s  $RES" $i; [ $(( i % 8 )) -eq 7 ] && echo
done
for j in {0..180..36}; do
  for i in {16..51}; do 
   k=$((i+j)); printf "${bg[$k]}${fg[$((i<34?15:0))]}%5s   $RES" $k; [ $(((i+2)%6 )) -eq 5 ] && echo
 done
done
for i in {232..255}; do 
 printf "${bg[$i]}${fg[$((i<244?15:0))]}%5s   $RES" $i;[ $(((i+2)%6)) -eq 5 ] && echo
done

PS: Und noch eine Vereinfachung (ohne die fg/bg Arrays)

1
2
3
4
5
6
7
8
#!/bin/bash
RES="\e[0m"; CLS=`clear`;fgbg="\e[48;5;%dm\e[38;5;%dm"
printf "$CLS\n$fgbg    Kleine Fingerübung mit 8 Bit ANSI-Farben    $RES\n\n" 19 226
for i in {0..15}; do printf "${fgbg}%4s  $RES" $i $((i<9?15:0)) $i; [ $(( i % 8 )) -eq 7 ] && echo;done
for j in {0..180..36}; do for i in {16..51}; do 
 k=$((i+j)); printf "${fgbg}%5s   $RES" $k $((i<34?15:0)) $k; [ $(((i+2)%6 )) -eq 5 ] && echo
done;done
for i in {232..255}; do printf "${fgbg}%5s   $RES" $i $((i<244?15:0)) $i;[ $(((i+2)%6)) -eq 5 ] && echo;done
Antworten |