Willkommen Gast. Bitte einloggen oder registrieren. Haben Sie Ihre Aktivierungs E-Mail übersehen?
03.08.2021, 22:11:34

.
Einloggen mit Benutzername, Passwort und Sitzungslänge

Mitglieder
  • Mitglieder insgesamt: 25802
  • Letzte: Duffman
Statistiken
  • Beiträge insgesamt: 748093
  • Themen insgesamt: 60184
  • Heute online: 557
  • Am meisten online: 2287
  • (22.01.2020, 19:20:24)
Benutzer Online

Autor Thema:  bash,Scriptproblem: Ein Array was bisher nur nur positive Zahlen verarbeit. kann  (Gelesen 568 mal)

0 Mitglieder und 1 Gast betrachten dieses Thema.

Das folgende Script dient als Quelle zur Erzeugung von einer einstellbaren Anzahl von Zahlen:
* es funktioniert so wie es ist
* je nach Angabe des Zahlenbereiches kann es wahlweise positive, negative als auch sowohl positive als auch negative Zahlen erzeugen

#!/bin/bash

        ug=-100     # lower limit   
        og=100      # upper limit
        n=100       # count of numbers

        for (( i=1; i<=n; i++ )); do # count of numbers   

                zufallszahl=$(( RANDOM % ( og - ug + 1 ) + ug )) # create a number from a range
                echo $zufallszahl # Ausgabe von Zufallszahl
            done         
        echo
        echo

read -p "Press Enter to exit or Ctl + C"

Im folgenden, habe ich obiges so erweitert, das es mir:
* den Zahlenbereich aus gibt als auch wie oft jede dieser Zahlen gewürfelt wurde
* die Ausgabe funktioniert auch in dieser Art und Weise wenn man nur positive Zahlen würfelt, jedoch nicht wenn man negative oder negative und positive Zahlen auf diese Art und Weise ausgeben will.

#!/bin/bash

    ug=0    # lower limit # mit z.B. -100 geht die Ausgabe des Arrays nicht   
    og=100  # upper limit
    n=100   # count of numbers

verteilung=()
        for (( i=1; i<=n; i++ )); do # count of numbers   

                zufallszahl=$(( RANDOM % ( og - ug + 1 ) + ug )) # create a number from a range
                # echo $zufallszahl # Ausgabe von Zufallszahl
                verteilung["$zufallszahl"]=$(( verteilung["zufallszahl"] + 1 ))
            done         
        echo
        echo

    for (( i=1; i<=n; i++ )); do
        echo "$i" "${verteilung[$i]}"
    done
echo
echo

read -p "Press Enter to exit or Ctl + C"

Laut folgender Quelle kann der Index eines bash Arrays nicht negativ sein:
* https://sysware.computer/linux/scripte_variablen_arrays.html

Frage:
* Können Array Stellen (Feldindex) wirklich nicht negativ sein ?
* Wie kann man das in einem Fall trotzdem realisieren ?
« Letzte Änderung: 17.07.2021, 11:47:12 von John.Miller »

Ok. Wenn man im konkreten Fall weiß um wieviel die Stellen un ter Umständen in den negativen Bereich rutschen, kann man mit einem Offset beim Beladen des Arrays arbeiten und beim entnehmen aus dem Array, wieder um diesen Wert die Arraystelle korrigieren.

Aber vlt. gibt es noch eine andere gängige Variante.


Nachtrag:
Ich habe jetzt gefunden das man das auch mit einem Assoziativen Array machen kann. Dann gibt es das Problem mit einem negativen Index nicht.
« Letzte Änderung: 18.07.2021, 22:51:58 von John.Miller »

#!/bin/bash

declare -A array

array[-1]="willkommen"
array[-2]="in"
array[-3]="der"
array[-4]="welt"
array[- fünf]="der"
array[minus 6]="assoziativen"
array[minus sieben]="arrays"


printf '%s ' ${array[-1]} ${array[-2]} ${array[-3]} ${array[-4]} ${array[- fünf]} ${array[minus 6]} ${array[minus sieben]} $'\n'

Ok. Wenn man im konkreten Fall weiß um wieviel die Stellen un ter Umständen in den negativen Bereich rutschen, kann man mit einem Offset beim Beladen des Arrays arbeiten und beim entnehmen aus dem Array, wieder um diesen Wert die Arraystelle korrigieren.
Diesen Gedanken hatte ich auch:
- die Ablage im Array verschieben: -100 auf Index 0, -99 auf Index 1, ..., -1 auf Index 99, 0 auf Index 100, 1 auf Index 101 u.s.w.
- oder die negativen anhängen: 0 auf Index  0, 1 auf Index 1, ..., 100 auf Index 100, -1 auf Index 101, -2 auf Index 102 u.s.w.
- oder ein zusätzliches Array mit positiven Indizes für die eigentlich negativen
(natürlich entsprechend angepasst auf ug und og)

Folgende Variante kommt ohne Verschiebung des Index aus und nutzt eine für mich bisher unbekannte Form eines bash Arrays, ein assoziatives Array:

#!/bin/bash

ug=0  # lower limit
og=50 # upper limit
n=50  # count of numbers

declare -A verteilung=()
for (( i=1; i<=n; i++ )); do
    (( zufallszahl = RANDOM % (og-ug+1) + ug ))
    (( verteilung[$zufallszahl]++ ))
done

for (( i=ug; i<=og; i++ )); do
  echo "$i ${verteilung[$i]}"
done

Sleep 30

Als nächstes will ich mal sehen ob man die als Array vorliegenden Daten, irgend wie per bash (also nicht per Python o.ä.) graphisch ausgeben kann. Da bin ich im Moment noch am recherchieren geeigneter Lösungen.

Für eine visuelle Ausgabe habe ich bisher folgende Lösungsansätze gefunden:
* v-barplot & h-barplot:
     * https://noqqe.de/blog/2012/04/01/ascii-statistik-graphen-mit-bash/
     * https://github.com/noqqe/statistical

Mit barplot kann man wohl so etwas in der Art machen:

$ ./v-barplot foo:24 bar:90 alice:76 bob:32
90 |    ###         
87 |    ###         
84 |    ###         
81 |    ###         
78 |    ###         
75 |    ### ###     
72 |    ### ###     
69 |    ### ###     
66 |    ### ###     
63 |    ### ###     
60 |    ### ###     
57 |    ### ###     
54 |    ### ###     
51 |    ### ###     
48 |    ### ###     
45 |    ### ###     
42 |    ### ###     
39 |    ### ###     
36 |    ### ###     
33 |    ### ###     
30 |    ### ### ###
27 |    ### ### ###
24 |### ### ### ###
21 |### ### ### ###
18 |### ### ### ###
15 |### ### ### ###
12 |### ### ### ###
 9 |### ### ### ###
 6 |### ### ### ###
 3 |### ### ### ###
   |================
    foo bar ali bob

Mal sehen was ich da noch so finde und wie das mit dem barplot einbinden funktioniert.
« Letzte Änderung: 18.07.2021, 09:40:22 von John.Miller »

Wenn man barplott wie folgt auf ruft, bekommet man unten stehende Ausgabe:

#!/bin/bash

./v-barplot.sh john:33 alice:9 linus:12 bob:31

sleep 30

32 |###             
30 |###         ###
28 |###         ###
26 |###         ###
24 |###         ###
22 |###         ###
20 |###         ###
18 |###         ###
16 |###         ###
14 |###         ###
12 |###     ### ###
10 |###     ### ###
 8 |### ### ### ###
 6 |### ### ### ###
 4 |### ### ### ###
 2 |### ### ### ###
   |================
    joh ali lin bob


Nun muss ich mal sehen wie ich die Ausgabe an v-barplot.sh übergeben bekomme.

#!/bin/bash

ug=0  # lower limit
og=50 # upper limit
n=50  # count of numbers

declare -A verteilung=()
for (( i=1; i<=n; i++ )); do
    (( zufallszahl = RANDOM % (og-ug+1) + ug ))
    (( verteilung[$zufallszahl]++ ))
done

for (( i=ug; i<=og; i++ )); do
  echo "$i ${verteilung[$i]}"
done

Sleep 30
« Letzte Änderung: 18.07.2021, 22:48:43 von John.Miller »

Für mich ist es nicht nicht offensichtlich wie man die aus folgendem für die Ausgabe zuständigen Codestück anpassen oder erweitern kann, das sie zu dem benötigten Format passt was die Grafikausgabesoftware benötigt:

Stelle des Codes der die Ergebnisse zeilenweise aus gibt:
[code]...
for (( i=ug; i<=og; i++ )); do
  echo "$i ${verteilung[$i]}"
done
[/code]

Beispiel für Ausgabe:
-5 2
-4 1
-3 2
-2 2
-1 4
0 1
1 1
2 3
3 1
4 2
5 1

benötigen tue ich folgendes Format:
var=-"5:2 -4:1 -3:2 -2:2 -1:4 0:1 1:1 2:3 3:1 4:2 4:1"
Mit diesem kann ich dann wie folgt die graphische Ausgabe machen:
#!/bin/bash

var=-"5:2 -4:1 -3:2 -2:2 -1:4 0:1 1:1 2:3 3:1 4:2 4:1"

./v-barplot.sh $var

sleep 30

In dieser Weise erhalte ich dann folgende Ausgabe:
4 |                ###                         
3 |                ###         ###             
2 |###     ### ### ###         ###     ###     
1 |### ### ### ### ### ### ### ### ### ### ###
  |============================================
   -5  -4  -3  -2  -1  0   1   2   3   4   4   

Wer kann mir sagen wie ich obige zeilenweise Ausgabe in folgende Form in eine Variable bekomme ?
var="-5:2 -4:1 -3:2 -2:2 -1:4 0:1 1:1 2:3 3:1 4:2 4:1"
Teillösung:
Folgende Variante setzt mir den benötigten Doppelpunkt und das benötigte Leerzeichen. Allerdings habe ich keine Ahnung wie ich die zeilenweise Ausgabe in eine innerhalb einer Zeile ändern kann und wie ich das in eine Variable bekomme:
for (( i=ug; i<=og; i++ )); do
    echo "$i:${distr[$i]}"" "
done
« Letzte Änderung: 18.07.2021, 23:28:27 von John.Miller »

Mit Hilfe der folgenden Anpassung kann man mit barplot graphische Ausgaben machen, sofern keine Stelle dabei ist die mit keinem Wert belegt ist, d.h. leer ist.:
...
barplot_var=$(for (( i=ug; i<=og; i++ )); do echo "$i:${distr[$i]}"" "; done)
#echo "$barplot_var"
./v-barplot.sh "$barplot_var"

Beispiel für Ausgabe:
1 12
-5 10
-4 12
-3 9
-2 9
-1 10
0 8
1 6
2 5
3 12
4 9
5 6

                                                                   
12 |    ###                         ###         
11 |    ###                         ###         
10 |### ###         ###             ###         
 9 |### ### ### ### ###             ### ###     
 8 |### ### ### ### ### ###         ### ###     
 7 |### ### ### ### ### ###         ### ###     
 6 |### ### ### ### ### ### ###     ### ### ###
 5 |### ### ### ### ### ### ### ### ### ### ###
 4 |### ### ### ### ### ### ### ### ### ### ###
 3 |### ### ### ### ### ### ### ### ### ### ###
 2 |### ### ### ### ### ### ### ### ### ### ###
 1 |### ### ### ### ### ### ### ### ### ### ###
   |============================================
    -5  -4  -3  -2  -1  0   1   2   3   4   5   

Bisher noch nicht gelöst:
* barplot funktioniert nicht, wenn ein Wert leer ist, was man jedoch mit einer Ersetzung 0 lösen können sollte.
« Letzte Änderung: 19.07.2021, 02:34:28 von John.Miller »

Zeichen kann man augenscheinlich mit tr austauschen:
* https://wiki.ubuntuusers.de/tr/

Vmtl. in etwa wie folgt:

#!/bin/bash

echo Vor Ersetzung:
var="-2:0 1:  1:5" # Beispiel Zeichenfolge
echo "$var" # var Inhalt vor Ersetzung
echo
echo

var=$"(("$var" | tr ": " ":0"))" # das ist noch irgend wie fehlerhaft
echo
echo

echo Nach Ersetzung:
echo "$var" # var Inhalt nach Ersetzung

sleep 30

Die auftretende Fehlermeldung lautet:
var=$"(("$var" | tr ": " ":0"))"
                          ^-- SC2140: Word is of the form "A"B"C" (B indicated). Did you mean "ABC" or "A\"B\"C"?
« Letzte Änderung: 19.07.2021, 10:40:49 von John.Miller »

var="-2:0 1:  1:5" # Beispiel Zeichenfolge
var="$( sed 's|: |:0|g' <<< "$var" )"

var="-2:0 1:  1:5" # Beispiel Zeichenfolge
var="$( sed 's|: |:0|g' <<< "$var" )"
Super. Damit funktioniert die Anpassung der Ausgabe der Nummernquelle an die graphische Ausgabe bestens.
Danke

Bei der Variante die mit tr arbeitet, bin ich noch am basteln:
geht:
var="-2:0 1:  1:5" # Beispiel Zeichenfolge
echo "$var" # var Inhalt vor Ersetzung
-2:0 1: 1:5 # Ausgabe

Was zwar noch fehlerhaft ist, aber bereits etwas macht:
echo "-2:0 1: 1:5" | tr ": " "0"
-2000100105 Ausgabe

Was zwar noch fehlerhaft ist, aber bereits etwas macht:
var="-2:0 1:  1:5" # Beispiel Zeichenfolge
echo "$var" | tr ": " "0"
-2000100105 Ausgabe

Bei meiner tr Variante scheint mir folgendes falsch zu sein:
": "


Tatsächlich braucht die Bash gar kein externes Tool wie sed oder tr für diese Aufgabe:
var="-2:0 1:  1:5" # Beispiel Zeichenfolge
var="${var//: /:0}"

Tatsächlich braucht die Bash gar kein externes Tool wie sed oder tr für diese Aufgabe:
Jetzt wo du das sagst, so was in der Art habe ich schon das habe ich schon mal so auf Stackoverflow gesehen.

Mit Variablen läßt sich das auch verwenden. Somit ist das eigentlich perfekt für mich.
#!/bin/bash

eingabe="-2:0 1:  1:5" # Beispiel Zeichenfolge
suchbegriff=":"
ersetzung=":0"

#ausgabe="${eingabe//: /:0}"
ausgabe="${eingabe/$suchbegriff /$ersetzung}"
echo "$ausgabe"

sleep 30

Die tr Variante fände ich der Vollständigkeit halber ganz interessant. Sozusagen zum Abheften, um das bei Bedarf verwenden zu können. Aber das hat nun Zeit, da ich ja jetzt eine verwendbare Lösung habe.
« Letzte Änderung: 19.07.2021, 14:22:32 von John.Miller »

Die tr Variante fände ich der Vollständigkeit halber ganz interessant.
Ich auch.   ;)

    Die tr Variante fände ich der Vollständigkeit halber ganz interessant.

Ich auch.   

zeichenfolge=Maus # Eingabe
zu_ersetzen=M
ersetzung=H

echo $a | tr $zu_ersetzen $ersetzung
Haus # Ausgabe