ka111
Anmeldungsdatum: 22. Juni 2014
Beiträge: 141
|
Guten Tag. Ich komme immer wieder an den Punkt an dem eine Variable mehr variabel sein sollte als sie kann. Deshalb wollte ich fragen ob jemand weiss wie ich mit Shell oder Bash eine Variable zusammen setzte, die vor dem = aus mehreren Variablen bestehen kann, und auch nach dem = aus mehreren Variablen. Ohne Zusatzbefehle wie echo, ausser es geht nicht anders und sie werden gleich schnell ausgeführt wie es ungefähr dauert eine Variable zu setzen oder ein einfaches if then (was bei mir mit echo nicht ist, eine Schleife mit Rechnungen und echo, sed, wc und dergleichen dauert gleich viel länger als ohne). Die einzige Ausnahme die ich gefunden habe ist eval, aber ohne echo. Und ich komme im Moment nicht mehr zum Inhalt der Variable, die einen variablen Namen hat, ohne eval echo. Es liegt aber nicht immer daran, es sollte einfach überall variabel sein, auf einfache gut merkbare Weise.
Also gibt es nicht eine Möglichkeit ohne zusätzliche Befehle eine Variable vor und nach dem = komplett variabel zusammen zu setzen? Ein Beispiel var1=2
var2=10
var3=100
var100=50
jetzt sollte man eine Variable so setzen können:
var"$var2"=$(( $var"$var3" + 20 ))
was das bedeuten sollte:
var10=$(( $var100 + 20 ))
ausserdem sollte auch so etwas gehen:
echo $var"$var1"
was 10 zurück geben sollte Wie mache ich das alles, ohne 5x einen zusätzlichen Befehl herbei zu nehmen? Weiss das vielleicht irgend jemand? Danke vielmals.
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11179
Wohnort: München
|
|
fleet_street
Top-Wikiautor
Anmeldungsdatum: 30. August 2016
Beiträge: 2143
Wohnort: Hunsrück
|
|
ka111
(Themenstarter)
Anmeldungsdatum: 22. Juni 2014
Beiträge: 141
|
Danke für die Antworten, aber ich glaube nicht das ich ein Array suche, aber ich muss mir Morgen einmal anschauen wie das alles mit Arrays funktionieren würde, ich hatte mich schon einmal über Arrays informiert und es hat nicht funktioniert. Aber ich schaue es mir sonst Morgen noch einmal an, weil das braucht sicher wieder viel Zeit. Soweit ich das aber verstanden hatte ist ein Array wie eine Variable, die mehrere Variablen beinhaltet? Es müsste dann sicher alles im Array auch variabel sein. Könnte man das was mit
echo $((5 + 10"$var1"))
ausgegeben wird in ein Array an eine Stelle bringen, ohne den echo Befehl? Wobei dann $var1 aus einem Platz aus einem Array kommen würde, das ist sehr komplex das abzuschätzen wie sich alles ändert, es wäre komplett anders gemacht, das müsste ich alles ausprobieren, ob das alles noch genau gleich machbar ist. Aber irgendwie habe ich den Verdacht dass das nicht immer funktionieren würde, spätestens wenn es nicht schön der Reihe nach aufgezählt wird und evtl. teilweise Buchstaben in den Variablen vorhanden sind. Ich schaue es mir Morgen mal soweit ich es verstehe an. Geht es den nicht auch ohne Arrays mit normalen Variablen? Weil eigentlich wäre es schon eher so gedacht das ich den Name und den Inhalt einer Variable zusammen schnippeln kann aus mehreren anderen Variablen die Zahlen und Buchstaben beinhalten können. Und auch mindestens den Inhalt müsste ich wieder heraus schnippeln können, auch wenn der Name variable ist durch mehrere Variablen.
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11179
Wohnort: München
|
Mit einem Array (ein assoziatives Array brauch man nur, wenn der Index bzw. Key kein Integer ist) könnte dein Beispiel so aussehen:
| declare -a myArray
myArray[1]=2
myArray[2]=10
myArray[3]=1000
myArray[100]=50
myArray[${myArray[2]}]=$(( myArray[3] + 20 ))
echo "${myArray[${myArray[1]}]}"
|
Kannst du vielleicht mal erklären, was da der konkrete Anwendungsfall ist? Mir erschließt sich noch nicht ganz, warum man sich das antun sollte - die Bash beherrscht keine verschachtelten Arrays - wenn man die für nötig hält, kann man sowas mit einer modernen Skriptsprache angehen.
|
ka111
(Themenstarter)
Anmeldungsdatum: 22. Juni 2014
Beiträge: 141
|
Ja, soweit ich hinterher komme sieht es so aus als ob ein Array beim jetzigen Beispiel wirklich das Problem löst, es ist einfach alles komplett anders aufgebaut dann, und ich kann schlecht abschätzen ob das überall funktioniert. Der Anwendungsfall ist der, das ich einen Wert vom Arduino bekomme, der innerhalb einem Wertbereich ist, und ausrechnen will prozentual wo der bekommene Wert dazwischen liegt, und dann diesen Wert einem 2. Arduino senden will. Also ich bekomme zB. 500, der Bereich kann zB. zwischen 100 und 900 sein (muss aber nicht, und es ist nicht schon vorher bekannt wo dieser Bereich liegt). Und somit würde 500 genau 50% entsprechen zwischen 100 und 900. Ich denke es würde wahrscheinlich sicher eine geeignetere Sprache dafür geben, ich möchte aber alles was möglich ist mit Shell oder Bash machen, weil um Shell komme ich fast nicht herum wenn man mit Linux zu tun hat, und je mehr Sprachen und Befehle ich lerne desto schlechter kann ich alles einzelne und fange mit der Zeit an die Sachen zu vermischen, da ich nicht so viel Scripte schreibe, manchmal wieder ein Jahr gar nicht. Und je mehr ich andere Sprachen anschaue desto mehr mag ich Shell/Bash (-:
|
ka111
(Themenstarter)
Anmeldungsdatum: 22. Juni 2014
Beiträge: 141
|
ein assoziatives Array brauch man nur, wenn der Index bzw. Key kein Integer ist
:O Soll das etwa bedeuten das es schon vorher bekannt sein muss ob ein Platz im Array eine Zahl oder etwas anderes beinhaltet? Oder gilt das vielleicht sogar für das ganze Array?? Das wäre dann unmöglich, nichts ist schlimmer als wenn von vorne herein bekannt sein muss ob es eine Zahl ist oder etwas anderes, mit dem kann ich nichts mehr machen. Unter anderem deshalb mag ich eben auch Bash, und nicht das C auf dem Arduino...
|
Doc_Symbiosis
Anmeldungsdatum: 11. Oktober 2006
Beiträge: 4390
Wohnort: Göttingen
|
Ja, normale Arrays haben eben natürliche Zahlen als Index, was übrigens nicht nur in der Bash so ist, sondern in den allermeisten Programmiersprachen.
|
ka111
(Themenstarter)
Anmeldungsdatum: 22. Juni 2014
Beiträge: 141
|
Hmm... Nein es scheint normal zu funktionieren, egal ob mit Zahlen oder Buchstaben. Eigentlich scheint auf den ersten Blick alles zu funktionieren, ausser im Moment grad einen doppelt variablen Array Name, aber das ist glaube ich auch nicht unbedingt nötig, da der Name des Platzes (der Variable im Array) doppelt variabel sein kann, und auch alles andere scheint ziemlich variabel zu sein. Sogar "echo "${myArray[${myArray[1]}]}" " das funktioniert, weil das 2. Array in den eckigen Klammern des 1. Arrays steckt. Kann man den nicht irgendwie mit Klammern und " ' Zeichen die 2. Variable von "$var$var2" auch einrahmen, so das sie auch abgesondert ist, wie in den eckigen Klammern des Arrays, und als eine einzige Variable einfügbar wird überall? Sonst sieht das eigentlich ziemlich gut aus, auch ziemlich ähnlich wie mit den normalen Variablen, ausser das {} verwendet wird.
Danke für das Beispiel mit den Arrays, das ist sehr nützlich (-: Edit: Zu spät gesehen, es funktioniert bei mir aber mit Zahlen und Buchstaben? Ich kann mit declare -a und -A überall Zahlen und Buchstaben mixen so wie ich das gesehen habe?
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11179
Wohnort: München
|
ka111 schrieb: Der Anwendungsfall ist der, das ich einen Wert vom Arduino bekomme, der innerhalb einem Wertbereich ist, und ausrechnen will prozentual wo der bekommene Wert dazwischen liegt, und dann diesen Wert einem 2. Arduino senden will.
Also ich bekomme zB. 500, der Bereich kann zB. zwischen 100 und 900 sein (muss aber nicht, und es ist nicht schon vorher bekannt wo dieser Bereich liegt). Und somit würde 500 genau 50% entsprechen zwischen 100 und 900.
Zwischen 100 und 900 liegen 800 Einheiten, 50% wären dann eigentlich bei 400 und 500 wären bei 62,5% ... Da reicht doch eine einfache Rechnung:
| v_min=100
v_max=900
value=500
span=$(( v_max - v_min ))
percent=$(( value * 100 / span )) # Integerrechnung
percent=$(echo "$value * 100 / $span" | bc -l ) # Fließkommazahlen
|
|
ka111
(Themenstarter)
Anmeldungsdatum: 22. Juni 2014
Beiträge: 141
|
Zwischen 100 und 900 liegen 800 Einheiten, 50% wären dann eigentlich bei 400 und 500 wären bei 62,5% ...
Ich meinte das nicht so, ich meinte 500 liegt genau in der Mitte zwischen 100 und 900, nicht 500 von 800 ist 62.5%. Und in deinem Beispiel weiss ich eigentlich nicht wieso Zeile 7 so gerechnet wird, wahrscheinlich ist das wegen dem Missverständnis vom Prozent. Ich hätte aber ähnlich gerechnet, bis Zeile 6 gleich, und nachher (value-v_min)*100/span. Könnte auch sein das sich da noch irgendwo ein Fehler befindet, habe das noch nicht getestet, aber das sollte ich schon bemerken und herausfinden. Es müsste einfach mit Arrays gemacht werden, da es bis zu 50 solcher Werte und Rechnungen haben kann, und alle möglichst ohne Zeitverzögerung weitergeleitet werden sollen. Von daher geht es nicht wenn noch überall echo oder bc drin steckt, aber Fliesskommazahlen brauche ich auch nicht, ich würde es wenn es nötig wäre einfach vervielfachen, das es halt nicht mehr Prozent sonder Pro-Million oder so wäre. Das probiere ich dann Morgen aus. Danke für die Hilfe Edit: Ausserdem werden die Werte zuerst in eine Datei geleitet und werden mit while read wieder heraus gelesen, dabei wird mit einer Variable gezählt, und diese Zahl ist zur gleichen Zeit eben auch die Zahl der Variable (die variabel sein sollte) oder jetzt neu der Platzname des Arrays
|
ka111
(Themenstarter)
Anmeldungsdatum: 22. Juni 2014
Beiträge: 141
|
Wäre zwar auch noch nützlich wenn man eine normale Variable auch so einrahmen kann damit sie wie ein Array einen doppelt variablen Namen haben kann. Weil mit Arrays muss man vorausschauend überlegen, ob die Variable jemals einen variablen Namen bekommt und mehrmals aufgezählt wird oder nicht. Wenn man es vergisst muss man wieder zurück und alles umschreiben... Kann man das nicht auch machen? Dann könnte ich mit Arrays fortfahren und müsste nicht alles was ich mit den Variablen jetzt gemacht habe umschreiben auf Arrays...
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11179
Wohnort: München
|
ka111 schrieb: Zwischen 100 und 900 liegen 800 Einheiten, 50% wären dann eigentlich bei 400 und 500 wären bei 62,5% ...
Ich meinte das nicht so, ich meinte 500 liegt genau in der Mitte zwischen 100 und 900, nicht 500 von 800 ist 62.5%.
Ah ok, der Wert ist da noch nicht auf den Bereich eingepasst - mir ist das aber immer noch nicht klar, warum man da dynamisch Variablen zusammenbauen muss - wenn ich weiß, dass ich für n Kanäle einen Wert bekomme, dann kann ich mir den Maximal- und Minimalwert für die Kanäle und das errechnete Ergebnis jeweils in einem Array merken und die Kanalnummer bzw. den Kanalnamen als Index nutzen, um den Wert nachzuschlagen - also z.B. für 3 Kanäle:
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 | declare -A c_max
declare -A c_min
c_max["Kanal 1"]=1000
c_min["Kanal 1"]=200
c_max["Kanal 2"]=1200
c_min["Kanal 2"]=150
c_max["Kanal 3"]=900
c_min["Kanal 3"]=100
function position_percent {
local channel="$1"
local value="$2"
local min=${c_min["$channel"]}
local max=${c_max["$channel"]}
value=$(( value - min ))
local span=$(( max - min ))
echo $(( value * 100 / span ))
}
declare -A c_results
c_results["Kanal 1"]=$(position_percent "Kanal 1" 300)
c_results["Kanal 2"]=$(position_percent "Kanal 2" 600)
c_results["Kanal 3"]=$(position_percent "Kanal 3" 500)
for channel in "${!c_results[@]}"
do
echo "${channel}: ${c_results[$channel]}"
done | sort
|
ka111 schrieb: Wäre zwar auch noch nützlich wenn man eine normale Variable auch so einrahmen kann damit sie wie ein Array einen doppelt variablen Namen haben kann. Weil mit Arrays muss man vorausschauend überlegen, ob die Variable jemals einen variablen Namen bekommt und mehrmals aufgezählt wird oder nicht. Wenn man es vergisst muss man wieder zurück und alles umschreiben... Kann man das nicht auch machen? Dann könnte ich mit Arrays fortfahren und müsste nicht alles was ich mit den Variablen jetzt gemacht habe umschreiben auf Arrays...
Du kannst statt $variable auch ${variable} schreiben, wenn du das meinst/willst.
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12822
|
ka111 schrieb:
Der Anwendungsfall ist der, das ich einen Wert vom Arduino bekomme, der innerhalb einem Wertbereich ist, und ausrechnen will prozentual wo der bekommene Wert dazwischen liegt, und dann diesen Wert einem 2. Arduino senden will. Also ich bekomme zB. 500, der Bereich kann zB. zwischen 100 und 900 sein (muss aber nicht, und es ist nicht schon vorher bekannt wo dieser Bereich liegt). Und somit würde 500 genau 50% entsprechen zwischen 100 und 900.
Langsam kommen wir der Sache näher. Verstehe ich das richtig, Du hast folgende Eingaben:
Unterer Wert eines Intervalls Oberer Wert eines Intervalls Messwert
Gesuchte Ausgabe
Prozentsatz des Messwerts im Bereich, also 100% * ( messwert - low ) / ( high - low )
Wofür benötigst Du dann eine Variable,
die vor dem = aus mehreren Variablen bestehen kann
? Ich glaube, Du hast das Problem noch nicht vollständig beschrieben. Ah, ich sehe, es gibt alles mehrfach: ka111 schrieb:
Es müsste einfach mit Arrays gemacht werden, da es bis zu 50 solcher Werte und Rechnungen haben kann, und alle möglichst ohne Zeitverzögerung weitergeleitet werden sollen. Von daher geht es nicht wenn noch überall echo oder bc drin steckt, aber Fliesskommazahlen brauche ich auch nicht, ich würde es wenn es nötig wäre einfach vervielfachen, das es halt nicht mehr Prozent sonder Pro-Million oder so wäre.
Wir sollten erst einmal das Problem klären, das gelöst werden muss. Um die effiziente Umsetzung kann man sich dann im zweiten Schritt kümmern.
Edit: Ausserdem werden die Werte zuerst in eine Datei geleitet
Dann poste bitte mal ein Beispiel der Eingabedatei. Da müssen nicht 50 Werte drin sein, aber ein paar, damit man sieht, wie die Datei formatiert ist.
und werden mit while read wieder heraus gelesen, dabei wird mit einer Variable gezählt, und diese Zahl ist zur gleichen Zeit eben auch die Zahl der Variable (die variabel sein sollte) oder jetzt neu der Platzname des Arrays
Der korrekte Begriff dürfte "Index" sein. Man spricht von "Array-Index". D.h. die Zuordnung von Messwerten zu Intervallen soll basierend auf dem Index gemacht werden. Korrekt? Wenn ich Dich weiterhin richtig verstehe, sind die Messwerte dynamisch, werden also ständig geliefert, aber die Intervalle sind fix. Korrekt?
|
ka111
(Themenstarter)
Anmeldungsdatum: 22. Juni 2014
Beiträge: 141
|
mir ist das aber immer noch nicht klar, warum man da dynamisch Variablen zusammenbauen muss - wenn ich weiß, dass ich für n Kanäle einen Wert bekomme, dann kann ich mir den Maximal- und Minimalwert für die Kanäle und das errechnete Ergebnis jeweils in einem Array merken
Ja das stimmt schon, ich meinte nur für wenn ich in Zukunft irgend ein anderes Script anfange, mit einer normalen Variable, die überall drin vernetzt ist, und ich irgendwann merke sie müsste jetzt ein Array sein. Dann müsste ich wieder alles umschreiben und die Variable durch ein Array ersetzen. Aber es ist nicht so wichtig, das mit den Arrays funktioniert so gut, ich könnte mir schon fast überlegen ob ich nicht standardmässig alle Variablen durch Arrays ersetze, ausser von denen, bei denen ich mit Sicherheit weiss das sie nie etwas anderes als immer den gleichen unvariablen Wert beinhalten werden. Wahrscheinlich ist es sogar einfacher sich die Darstellung des Arrays zu merken als 3 spezial Verschachtelungen von einer normalen Variable mit 3 verschiedenen Sonderzeichen. Bei deinem letzten Beispiel weiss ich eigentlich nicht wieso dort alles so gerechnet wird, wie es wird, und ich verstehe auch ein paar Befehle nicht so ganz. Aber ich wüsste jetzt schon wie ich ein Array für meinen Zweck benutzen muss. Ich würde das glaube ich auch etwa so ähnlich machen.
Du kannst statt $variable auch ${variable} schreiben, wenn du das meinst/willst.
Ich meinte eigentlich wie man $var$var2 ausgibt, aber es nicht so wichtig. Ich probiere mal ein paar Sachen mit all dem aus... Edit: Ah da wurde schon wieder etwas geschrieben, muss auch kurz alles durchlesen, überlegen, und antworten...
|