ka111
(Themenstarter)
Anmeldungsdatum: 22. Juni 2014
Beiträge: 141
|
Also es bleibt eigentlich die Frage, wie bringe ich die 1, 2 und 3 stelligen Werte aus den verschiedenen Variablen (oder Arrays) wieder 3 stellig, zusammengefasst in eine einzige Variable, innerhalb von max 0.02s. Das geht ungefähr so lange wie 1 sed -i Befehl, oder 1x "while read line" durch die Eingabedatei. Entweder ist die Geschwindigkeit von echo $(echo 123456) das Problem oder der Abstand zwischen allen Indexen, wenn ich das ganze Array auf einmal ausgeben will. Idealerweise würde das im "while read line" durchgang passieren, mit geschicktem Rechnen und Variable setzen. Sagen wir ich habe 50 Variablen, j1 -j50. Die sind 1-3 stellig und müssen alle entweder 2 stellig oder 3 stellig nahtlos in eine einzige Variable zusammengebracht werden. Wie mache ich das innerhalb der Dauer, die etwa 1 sed -i Befehl braucht um 50 Zeilen zu löschen? Mit v1="printf für jede der 50 Variablen" geht es schon mal nicht, das braucht viel zu lange, komischerweise. Im Gegensatz zu 50 einzelnen printf, das geht nicht einmal 0.01s, in der Variable über 0.1s.
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17548
Wohnort: Berlin
|
Ohne zu schauen, ob es für Deinen Code relevant ist, lässt sich allgemein sagen: Externe Programme aufzurufen (sed, wc, tr) dauert oft länger, als eine shellinterne Funktion aufzurufen. Die Shell ist aber nicht so mächtig, wie sed und Konsorten, das wäre der Punkt, wonach ich schauen würde, müsste ich das unter Zeitdruck beschleunigen, koste es was es wolle. Im Bashmanual findest Du zu Stringmanipulation im Abschnitt Parameter Expansion die Dokumentation. Ansonsten ist das Skript zwar aufgeräumt, aber gräßlich. Vorne ein Riesenblock an Variablen, die alle lange vor dem ersten Gebrauch definiert werden, statt unmittelbar davor - da findet man sich natürlich nicht zurecht. Das entspricht zwar einem Ordnungsschema, aber ist völlig sinnlos. Auch stört das Fehlen von Funktionen. Statt mit bombastischen Kommentaren einen Block zu verzieren, verzier ihn mit einer Funktion mit aussagekräftigem Namen. Ebenso Variablennamen:
| a1="/pfad/zum/hauptordner" # haupt ordner
hauptordner="/pfad/zum/hauptordner"
|
Das dokumentiert sich selbst:
| a8="$a1/speicher"
a9="$a8/speicher4"
|
Das sieht aus wie eine Division.
| speicher="$hauptordner/speicher"
speicher4="$speicher/speicher4"
|
Das sieht aus wie Pfade. Im Code
| e3=1 # variable zurücksetzen für while
while read -r line; do # while read = if arduino speicher (speicher3) > 50 (e3) zeilen
if [ $e3 = 1 ]; then
eval 'j'$e1=$line # rechnung
$e3=$(($e3+1))
done < $a8/speicher3
|
fehlt ein fi. Variablen deklarieren, die man nur einmal nutzt, das auch noch 200 Zeilen später, ist keine gute Idee. Als vertical Space nimmt man zur Gliederung entweder 1 oder 0 Zeilen Abstand. Mit 3, 4, 5 Zeilen etwas ausdrücken zu wollen, ist Quatsch. Wahrscheinlich fehlt da eine benannte Funktion. So beim ersten Drübersehen. Es gibt auch keinen plausiblen Grund, Variablen, die nichts miteinander zu tun haben, a1, a2, a3 zu nennen. Die Variablen a3 und a4 werden gar nicht verwendet. Leider meckert das Shellcheck nicht an. Wie viele gibt es noch? Arduinoport 1 und 2 heißen bei Dir a2 und a10 - welchem Plan folgt das? Wieso nicht port1 und port2?
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17548
Wohnort: Berlin
|
ka111 schrieb: user_unknown Es ist jetzt das gekürzte Script unten von mir editiert, da ist es mit 2en gemacht.
Nein.
Hä? Doch es ist mit 2en gemacht, genau so wie ich es im ganzen Script gemacht habe, nur übersichtlich.
In Deinem Posting war unten kein Code.
user_unknown Und komm nicht auf die Idee das Skript als Anhang anzufügen. Setz es in einen Codeblock.
Willst du jetzt wirklich das ganze Script mit allen nicht mehr funktionierenden Teilen, obwohl ich es unten zusammengefasst und verkürzt dargestellt habe? Einen Moment mal, ich füge es nachher an... user_unknown Arrays sind wie gesagt schneller:
Ja aber ich glaube es liegt einfach an dem Problem das echo 12345 0.000s braucht, aber echo $(echo 123456) 0.016 bei mir, auch mit printf. Und irgendwie muss ich am Schluss so etwas am Arduino senden "echo 101100:102050", und das mit max 50 6er Blöcken, und zwar mit dieser Art von Variablen: "echo 1$v1$x1" oder "echo 1$(printf "%02d\n" $v1)$(printf "%03d\n" $v2)". Auch wenn ich ein Array erstelle muss ich printf benutzen wegen der 3er Stelle, oder ich müsste den ganzen Inhalt des Arrays ohne Abstand zwischen den Indexen ausgeben können (soweit ich das jetzt abschätzen kann). Oder wie würdest du aus den Werten in den Variablen wieder 6er Blöcke zusammen bauen?
Dadrauf kommen wir noch. Hier mal Dein Script nach einem ersten Aufräumversuch:
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233 | #!/bin/bash
hauptordner="/pfad/zum/hauptordner"
port1="/dev/ttyUSB0";
# a3="nächster ordner pfad" # nächster ordner
# a4="10" # gpio pin für servo strom ein
speicher="$hauptordner/speicher"
# a9="$speicher/speicher4"
port2="/dev/ttyUSB1"; # 2. arduino port
d1=01 # photosensor 1
d2=02 # photosensor 1
d3=03 # photosensor 1
d4=04 # photosensor 1
d5=05 # photosensor 1
# d6=06 # photosensor 1
e1=6 # anzahl photosensoren
pause=5 # verzögerungs zeit
e3=1 # aktuellem photosensor variabel zahl für schleife
e5=301000 # erster sensor abfrage befehl, für auflistung aller arduino2 befehle in einem satz
# e6=101000 # variable für servo befehle zusammen an arduino senden
# alle g variablen sind für photosensor wert aufnahme max reserviert, gleiche anordnung wie d variablen
# alle h variablen sind für differenz zwischen f und g
# alle i variablen sind für + oder -, bei differenz zwischen f und g, wird nur i=f oder g gesetzt
# alle j variable sind für servo winkel befehl an arduino1 senden
arduinoVerbinden () {
echo ""
echo "verbinde 2. arduino"
pfad/zum/script* # 2. arduino verbinden
sleep 3
echo 000000 > $port2 # weil nach neustart vom arduino die erste rückmeldung alles überschreibt, sonst stimmt die reihenfolge nicht
sleep 1 # sleep zeit zu erster start obige zeile
echo ""
echo "fertig"
}
# warten bis 2. arduino speicher alle zeilen erhalten hat, und fertig
warteAufAdruino2 () {
grenzwert=$1
while true
do
if [ "$(wc -l $speicher/speicher3 | cut -d" " -f1)" -lt $grenzwert ]
then
sleep 0.001
else
break
fi
done
}
aufnahmeSensorWerteMinMax () {
# aufnahme der sensor werte min und max
echo "beginne"
echo "min start"
echo "erfasse werte"
sleep $pause
echo "0" > $speicher/speicher3 # arduino Kommunikationsspeicher leeren
echo 3"$d1"000 > $port2
echo 3"$d2"000 > $port2
echo 3"$d3"000 > $port2
echo 3"$d4"000 > $port2
echo 3"$d5"000 > $port2
}
initPhotoSensor () {
# alle f variablen sind für photosensor wert aufnahme min reserviert, gleiche anordnung wie d variablen
# alle min sensor werte aufnehmen in f variablen, tr weil noch unsichtbare zeichen a sind
f1=$(sed -n 3p $speicher/speicher3 | tr -dc '0-9')
f2=$(sed -n 5p $speicher/speicher3 | tr -dc '0-9')
f3=$(sed -n 7p $speicher/speicher3 | tr -dc '0-9')
f4=$(sed -n 9p $speicher/speicher3 | tr -dc '0-9')
f5=$(sed -n 11p $speicher/speicher3 | tr -dc '0-9')
}
initMeldung () {
minmax=$1
aktion=$2
echo
echo "${minmax}-"Werte aufgenommen
echo
echo "max start"
echo "$aktion"
sleep $pause
}
# arduino Kommunikationsspeicher leeren
komSpeicherLeeren () {
echo "0" > $speicher/speicher3
echo 3"$d1"000 > $port2
echo 3"$d2"000 > $port2
echo 3"$d3"000 > $port2
echo 3"$d4"000 > $port2
echo 3"$d5"000 > $port2
}
# alle min sensor werte aufnehmen in g variablen, tr weil noch unsichtbare zeichen da sind
sensorwerteAufnehmen () {
g1=$(sed -n 3p $speicher/speicher3 | tr -dc '0-9')
g2=$(sed -n 5p $speicher/speicher3 | tr -dc '0-9')
g3=$(sed -n 7p $speicher/speicher3 | tr -dc '0-9')
g4=$(sed -n 9p $speicher/speicher3 | tr -dc '0-9')
g5=$(sed -n 11p $speicher/speicher3 | tr -dc '0-9')
}
arduinoVerbinden
aufnahmeSensorWerteMinMax
warteAufAdruino2 11
# initPhotoSensor
initMeldung "min" "erfasse Werte"
komSpeicherLeeren
warteAufAdruino2 11
sensorwerteAufnehmen
initMeldung "max" "erfasse Werte"
echo "0" > $speicher/speicher3 # arduino kommunikations speicher leeren
echo 3"$d1"000 > $port2
warteAufAdruino2 3
# alle min sensor werte aufnehmen in f variablen, tr weil noch unsichtbare zeichen da sind
f6=$(sed -n 3p $speicher/speicher3 | tr -dc '0-9')
initMeldung "min" "nehme Werte auf"
# arduino kommunikations speicher leeren
echo "0" > $speicher/speicher3
echo 3"$d1"000 > $port2
warteAufAdruino2 3
# alle min sensor werte aufnehmen in g variablen, tr weil noch unsichtbare zeichen da sind
g6=$(sed -n 3p $speicher/speicher3 | tr -dc '0-9')
echo
echo "alle werte aufgenommen"
echo
### vor rechnen für haupt script
echo
echo "berechne..."
# unterschied zwischen f und g ausrechnen
e3=1 # variable zurücksetzen, variablen zahl aufzählung für while
while [ $e3 -le $e1 ]; do
if [ $(eval 'echo $f'$e3) -lt $(eval 'echo $g'$e3) ]; then # wenn f < g, dann g-f und i=f, sonst umgekehrt
eval 'h'$e3=$(( $(eval 'echo $g'$e3) - $(eval 'echo $f'$e3) ))
eval 'i'$e3=$(eval 'echo $f'$e3)
elif [ $(eval 'echo $g'$e3) -lt $(eval 'echo $f'$e3) ]; then
eval 'h'$e3=$(( $(eval 'echo $f'$e3) - $(eval 'echo $g'$e3) ))
eval 'i'$e3=$(eval 'echo $g'$e3)
else echo ""
echo "ERROR"
fi
((e3+=1)) # aufzählungsvariable +1
done
# Sensorbefehlsabfrage in einem Satz ausrechnen
# e3=2 # variable auf passenden wert zurücksetzen für while
# while [ $e3 -le $e1 ]; do
# e5="$e5":3"$(eval 'echo $d'$e3)"000
# ((e3+=1))
# done
for (( i=2; i <= e1; i+=1))
do
e5="$e5":3"$(eval 'echo $d'$e3)"000
done
echo
echo "fertig"
### haupt script
# vorgängig
echo "0" > $speicher/speicher3 # arduino kommunikations speicher leeren
sed -i '1d' $speicher/speicher3 # einzige zeile aus speicher3 löschen
echo "$e5" > $port2 # vorgängige sensor wert abfrage
e4=3 # aufzähl variable für sensor wert aufnahme, und werte aus arduino speicher holen
while true
do
echo "$e5" > $port2 # sensor wert abfrage
e3=1 # variable zurücksetzen für while
while read -r line; do # while read = if arduino speicher (speicher3) > 50 (e3) zeilen
if [ $e3 = 1 ]; then
eval 'j'$e1=$line # rechnung
fi
((e3+=1))
done < $speicher/speicher3
e3=1 # variable zurücksetzen, variablen zahl aufzählung für while
echo "0" > $speicher/speicher3 # arduino kommunikations speicher leeren
while [ $e3 -le $e1 ]; do
echo 3"$(eval 'echo $d'$e3 )"000 > $port2 ################################### <--- dieser befehl muss von hand aufgezählt werden ohne schleife mit / zwischen zahlen
e3=$(($e3+1)) # aufzählungsvariable +1
echo "send"
date +%S.%N
echo 3"$(eval 'echo $d'$e3 )"000
done
#echo "send"
#date +%S.%N
# sensor werte aus arduino speicher lesen, in prozent umwandeln und winkel befehl senden
e3=3 # variable zurücksetzen auf erste zeile von sensor wert aus arduino speicher, variablen zahl aufzählung für while
# wenn aktueller sensor/winkel max anzahl an sensoren/winkel überschreitet, *2 +1 weil asl erstes 0 zum überschreiben geschrieben wird, und dann 2 zeilen für jeden sensor wert (0 antwort, und wert)
while [ $e3 -le $((e1*2+1)) ]
do
echo "empfang"
date +%S.%N
# sensor wert in variable speichern aus 2. arduino speicher, tr weil unsichtbare zeichen sonst vorhanden sind
e4=$(sed -n $(($e3))p $speicher/speicher3 | tr -dc '0-9')
echo " $e4"
#echo "1"$(eval 'echo $d'$(($(($e3-1))/2)) )
#echo $(printf "%03d\n" "$(($(( 180000000/$(eval 'echo $h'$(( $(($e3-1)) /2)) ) * $(($e4 - $(eval 'echo $i'$(( $(($e3-1)) /2)) ) )) )) /180000))")
echo "befehl: $(echo "1"$(eval 'echo $d'$(($(($e3-1))/2)) )""$(printf "%03d\n" "$(($(( 180000000/$(eval 'echo $h'$(( $(($e3-1)) /2)) ) * $(($e4 - $(eval 'echo $i'$(( $(($e3-1)) /2)) ) )) )) /1000000))")"" )"
# rechnen und winkel befehl senden, printf weil nur so ist winkel zahl immer 3 stellig
echo "1"$(eval 'echo $d'$(($((e3-1))/2)) )""$(printf "%03d\n" "$(($(( 180000000/$(eval 'echo $h'$(( $((e3-1)) /2)) ) * $(($e4 - $(eval 'echo $i'$(( $((e3-1)) /2)) ) )) )) /1000000))")"" > $port1
((e3+=2))
done
#echo "empfang"
#date +%S.%Nc
done
killall cat # cat wegen 2. arduino beenden
$hauptordner/scripte/2.* # 1. arduino wieder verbinden und cat neu starten
|
Da ist noch mehr aufzuräumen, aber ein Anfang wäre gemacht.
Dass da bei WartenAufArduino2 3x fast das gleiche passiert, das muss einem doch auffallen! Da übergibst Du einer Funktion einen Paramter, der dann in der Funktion als $1 (, $2, $3) zur Verfügung steht. Da benennt man den entsprechend und kann die Funktion wiederverwenden. Wenn man eine Verbesserung hat, muss man sie nur 1x schreiben, nicht 3x.
Klingt mir nach einer unglaublichen Kollegschaft 😀
Aber für mich ist es ok formatiert.
Das sieht man an den Hemmungen das Skript zu zeigen.
Eigentlich sieht es gar nicht so schlecht aus, es ist einfach komplex aufgebaut,
Nein, es ist planloses copy-paste mit einer Pseudoordnung, alle Variablen oben erst mal feierlich zu kommentieren, weit über die Hälfte davon gar nicht zu benutzen, eine Zählvariable e3 zu nennen und alle Nase lang wiederzuverwenden, als hätten diese e3s irgendwas miteinander zu tun.
und es nützt dir nichts wenn du nicht weisst was gedacht wurde beim erstellen
Du weißt in 6 Monaten auch nicht mehr, das a2 port1 und a10 port2 ist.
und machen all dieser Variablen, denke ich mal. Sonst sollte das editierte kurz Script eigentlich schon alles aussagen... Aber warte mal kurz...
Eine Aufzählung ist übrigens "Erbsen, Möhren, Mais", dagegen ist "1, 2, 3" nur eine Zählung.
Schleifen, die eine bestimmte Zahl an Durchläufen absolvieren, schreibt man mit einer for-loop, dafür wurde sie gemacht.
Da habe ich nur ein Beispiel hinterlassen. Für den Zähler verwendet man immer ein frisches i, evtl. ein n oder x, bei verschachtelten Schleifen auch mal ein j. Aber nicht e3, das in keiner Beziehung zu e2 oder e4 steht. Man kommentiert nicht, dass man das hochzählt. Wenn doch: | e3=$(($e3+2)) # aufzählungsvariable +1
|
So besser nicht. Kommentare schreibt man nicht für Nichtprogrammierer, die e3=$ nicht verstehen. Den durchschnittlichen Shellprogrammierer sollte man vor Augen haben. | echo 000000 > $port2 # weil nach neustart vom arduino die erste rückmeldung alles überschreibt, sonst stimmt die reihenfolge nicht
|
Das ist ein recht guter Kommentar, weil er etwas sehr fachspezifisches erläutert. Nicht so gut ist die durchgängige Kleinschreibung. Im Gegensatz zu vielen anderen Sprachen ist die Wortstellung im Deutschen in Sätzen sehr variabel. Deswegen hilft Groß-Kleinschreibung beim Lesen. | f6=$(sed -n 3p $speicher/speicher3 | tr -dc '0-9')
|
Solche Zeilen kommen mit wechselndem Wert statt 3p häufig vor. Sowas gehört auch in eine Funktion. Zeile x soll aus der Datei speicher3 gelesen, und um alles, was keine Ziffer ist, gekürzt werden. Das kann sed, dann braucht man nicht 2 externe Programme aufzurufen: | # [^0-9] löschen, weil noch unsichtbare Zeichen da sind
liesZiffernAusZeile () {
zeile=$1
sed -n "$zeile s/[^0-9]//g" $speicher/speicher3
}
f6=$(liesZiffernAusZeile 3)
|
Redundanzen erkennen und abstrahieren (hier: über die Zeilennummer abstrahieren). Bei strukturierter Programmierung auch richtig einrücken, bitte. Was soll eigentlich dieser Code: | e4=3 # aufzähl variable für sensor wert aufnahme, und werte aus arduino speicher holen
|
Also noch so eine Zählvariable.
Aber wo wird sie das nächste Mal verwendet?
30 Zeilen später, und zwar so:
| e4=$(liesZiffernAusZeile $e3)
|
Weder wurde die 3 zwischenzeitlich verwendet, noch gibt es einen Pfad zur Auswertung der Variablen, der an der zweiten Initialisierung vorbei geht. Die erste Initialisierung gehört ersatzlos gestrichen. Shellcheck meldet übrigens doch ungenutzte Variablen: 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 | In arduino.sh line 81:
f1=$(liesZiffernAusZeile 3)
^-- SC2034: f1 appears unused. Verify it or export it.
In arduino.sh line 82:
f2=$(liesZiffernAusZeile 5)
^-- SC2034: f2 appears unused. Verify it or export it.
In arduino.sh line 83:
f3=$(liesZiffernAusZeile 7)
^-- SC2034: f3 appears unused. Verify it or export it.
In arduino.sh line 84:
f4=$(liesZiffernAusZeile 9)
^-- SC2034: f4 appears unused. Verify it or export it.
In arduino.sh line 85:
f5=$(liesZiffernAusZeile 11)
^-- SC2034: f5 appears unused. Verify it or export it.
In arduino.sh line 111:
g1=$(liesZiffernAusZeile 3)
^-- SC2034: g1 appears unused. Verify it or export it.
In arduino.sh line 112:
g2=$(liesZiffernAusZeile 5)
^-- SC2034: g2 appears unused. Verify it or export it.
In arduino.sh line 113:
g3=$(liesZiffernAusZeile 7)
^-- SC2034: g3 appears unused. Verify it or export it.
In arduino.sh line 114:
g4=$(liesZiffernAusZeile 9)
^-- SC2034: g4 appears unused. Verify it or export it.
In arduino.sh line 115:
g5=$(liesZiffernAusZeile 11)
^-- SC2034: g5 appears unused. Verify it or export it.
In arduino.sh line 134:
f6=$(liesZiffernAusZeile 3)
^-- SC2034: f6 appears unused. Verify it or export it.
In arduino.sh line 145:
g6=$(liesZiffernAusZeile 3)
^-- SC2034: g6 appears unused. Verify it or export it.
|
(Die Zeilennummern weichen sicher inzw. ein wenig ab - ich habe in meinem Editor noch weitere Änderungen gemacht).
Beim ersten Mal hat das fehlende fi den Analyzer wohl zu sehr aus dem Tritt gebracht, um das zu melden.
|
ka111
(Themenstarter)
Anmeldungsdatum: 22. Juni 2014
Beiträge: 141
|
Ou shit, du hast das ganze Script durchgesehen und verbessert! Ich danke dir wirklich vielmals, aber es funktioniert doch gar nicht mehr richtig... Ich muss das halbe Script wieder umschreiben, der ganze Abschnitt im Hauptscript funktioniert gar nicht mehr, und oberhalb davon muss ich wegen dem "warten bis der Arduino Rückmeldung gegeben hat" nochmals schauen, weil ich da etwas geändert habe auf dem Arduino gibt er keine Rückmeldung mehr einfach so. user_unknown Dass da bei WartenAufArduino2 3x fast das gleiche passiert, das muss einem doch auffallen! Da übergibst Du einer Funktion einen Paramter, der dann in der Funktion als $1 (, $2, $3) zur Verfügung steht. Da benennt man den entsprechend und kann die Funktion wiederverwenden. Wenn man eine Verbesserung hat, muss man sie nur 1x schreiben, nicht 3x.
Ich kenne $1, $2, $3 nicht, ich hatte vor etwa 2 Tagen das kurz angeschaut, und bin grad nicht draus gekommen... Ich weiss nicht einmal was mit Parameter eigentlich genau gemeint ist. Ich bin aber nicht sicher wie du das meinst, denkst du ich versuche die gleiche Variable 3x zu holen? Der Arduino hat bevor ich etwas darauf geändert hatte immer 0 gesendet wenn er den Befehl ausgeführt hat, und ich wartete bis jetzt meistens bis ich diese Rückmeldung erhalten habe, bin eben gar nicht mehr sicher ob ich das jetzt in diesem Script überhaupt brauche, ich muss es nochmals anschauen, es ist ja nicht im Zeitkritischen Bereich. user_unknown Eigentlich sieht es gar nicht so schlecht aus, es ist einfach komplex aufgebaut,
Nein, es ist planloses copy-paste mit einer Pseudoordnung, alle Variablen oben erst mal feierlich zu kommentieren, weit über die Hälfte davon gar nicht zu benutzen, eine Zählvariable e3 zu nennen und alle Nase lang wiederzuverwenden, als hätten diese e3s irgendwas miteinander zu tun.
Das stimmt, vieles wurde 1x gemacht und dann immer wieder kopiert und eingefügt, aber nicht planlos. Alle Variablen will ich oben auflisten, damit ich weiss bei welcher Variable ich eigentlich schon wieder bin. Und es kann auch sein das nicht alle genutzt werden, bin nicht mehr sicher ob ich nicht aus dem vorherigen Script einfach alle in dieses neue hineinkopiert habe, aber nur wenige Teile des Scriptes dann auch wieder hinein kopiert habe. Und gewisse von den ersten 10, 15 a Variablen werden gar nicht gebraucht in diesem Script, zB der Port vom 1. Arduino wird nur in dem sehr kurzen anderen Script gebraucht das den Arduino startet, sonst eigentlich nicht. Aber ich wollte alle Variablen bei jedem Script wieder einfügen (von den a), damit ich wenn ich von irgendwo einen Teil heraus kopiere er auch im anderen funktioniert, wegen den Pfaden, und auch damit ich es einfach habe den Pfad zu ändern falls ich mal den Ordner verschiebe, und nicht dann in jedem Script überall alles durchsuchen muss wo der veraltete Pfad überall benutzt wurde. Und das mit den e1, e2, e3 ..., das mache ich halt so, ich brauche eine Variable für irgend etwas, dann die nächste, dann wieder die nächste. Ausser mir fällt auf das ich sie gut mehrmals verwenden kann, weil sie eben nur ein while Zähler ist. user_unknown Du weißt in 6 Monaten auch nicht mehr, das a2 port1 und a10 port2 ist.
Ja das stimmt, ich weis es auch meistens schon beim nächsten mal wenn ich den Pfad brauche nicht mehr, deshalb liste ich oben alles auf und habe in einem 2. Terminal den Anfang des Scriptes damit ich nachschauen kann welche Variable das ich jetzt brauche. Ist immer noch besser als wenn sich ein Pfad ändert den überall in jedem Script zu suchen. Ausser man würde es mit grep oder so suchen oder gleich mit sed ersetzen... user_unknown Schleifen, die eine bestimmte Zahl an Durchläufen absolvieren, schreibt man mit einer for-loop, dafür wurde sie gemacht
Aha ok, gut zu wissen. Aber ich habe nie nachgeschaut wie eine for loop funktioniert, hatte das vor Jahren am Anfang mal angeschaut, und bin grad nicht draus gekommen und hatte auch nie einen Grund etwas anderes als eine while Schleife zu verwenden. Auch das while read line kannte ich bis zum Hauptscript nicht, ich musste noch nie jede Zeile einer Datei durchsuchen, nur bestimmte Zeilen, die ich mit sed -n Xp herausgesucht hatte. user_unknown Für den Zähler verwendet man immer ein frisches i, evtl. ein n oder x, bei verschachtelten Schleifen auch mal ein j. Aber nicht e3, das in keiner Beziehung zu e2 oder e4 steht. Man kommentiert nicht, dass man das hochzählt.
😀 Ich bin ja auch nicht im schön schreiben, ist doch egal wie ich das nenne, hauptsache ich komme draus 😀 wie gesagt, ich schreibe es ja nicht für jemand anderen, nur für mich, war keine Absicht dass das jemals jemand anderes sieht. user_unknown Nicht so gut ist die durchgängige Kleinschreibung. Im Gegensatz zu vielen anderen Sprachen ist die Wortstellung im Deutschen in Sätzen sehr variabel. Deswegen hilft Groß-Kleinschreibung beim Lesen.
😀 Das selbe... user_unknown Solche Zeilen kommen mit wechselndem Wert statt 3p häufig vor. Sowas gehört auch in eine Funktion.
Zeile x soll aus der Datei speicher3 gelesen, und um alles, was keine Ziffer ist, gekürzt werden.
Das kann sed, dann braucht man nicht 2 externe Programme aufzurufen:
Ich könnte tatsächlich gewisse Teile des Scriptes in einen function Befehl packen, damit ich einen besseren Überblick habe über den Ablauf. Aber ich habe auf eine Art angefangen und es dann nicht gemacht, und letzten Endes ist dann halt einfach die Unübersicht bei allen Funktionen, anstatt im ganzen Script, was aber etwas besser sein könnte. Kann ich mir am Schluss nochmals überlegen ob ich das machen will. Und sed ist der Befehl den ich am wenigsten mag, wegen der Darstellung mit allen Sonderzeichen. Ich komme bei sed nie draus, deshalb vermeide ich es wann immer möglich. Nur sed -i und sed -n Xp scheint mir einfach verständlich. user_unknown Was soll eigentlich dieser Code:
e4=3 # aufzähl variable für sensor wert aufnahme, und werte aus arduino speicher holen
Also noch so eine Zählvariable. Aber wo wird sie das nächste Mal verwendet? 30 Zeilen später, und zwar so:
e4=$(liesZiffernAusZeile $e3)
Weder wurde die 3 zwischenzeitlich verwendet, noch gibt es einen Pfad zur Auswertung der Variablen, der an der zweiten Initialisierung vorbei geht. Die erste Initialisierung gehört ersatzlos gestrichen.
Ich weiss es jetzt auch nicht mehr, vielleicht hatte ich mir dabei etwas gedacht, das ich vielleicht später noch etwas mache damit ich das brauche, oder ich weis es jetzt grad auch nicht mehr, vielleicht auch übersehen... user_unknown Ohne zu schauen, ob es für Deinen Code relevant ist, lässt sich allgemein sagen:
Externe Programme aufzurufen (sed, wc, tr) dauert oft länger, als eine shellinterne Funktion aufzurufen. Die Shell ist aber nicht so mächtig, wie sed und Konsorten, das wäre der Punkt, wonach ich schauen würde, müsste ich das unter Zeitdruck beschleunigen, koste es was es wolle.
Das ist sehr gut zu wissen, danke. Aber ich glaube ich nutze sowieso nur einen Bruchteil von dem was Bash könnte. Aber könnte man den zB den printf Befehl dazu benutzen um 1 Zahl auszugeben, dann direkt eine immer 2 Stellige angehängt, dann nochmals eine immer 3 stellige, dann einen Doppelpunkt, und wieder von vorne? Ohne eben "printf 1$(printf 2 stellig)" zu nutzen? Also nur ein einziges mal printf am Anfang, und nur gewisse Zahlen in 3 stellige umwandeln? user_unknown Ansonsten ist das Skript zwar aufgeräumt, aber gräßlich. Vorne ein Riesenblock an Variablen, die alle lange vor dem ersten Gebrauch definiert werden, statt unmittelbar davor - da findet man sich natürlich nicht zurecht. Das entspricht zwar einem Ordnungsschema, aber ist völlig sinnlos.
Auch stört das Fehlen von Funktionen. Statt mit bombastischen Kommentaren einen Block zu verzieren, verzier ihn mit einer Funktion mit aussagekräftigem Namen.
Ebenso Variablennamen
Ist eigentlich auch schon erklärt, ich mach das halt eben einfach so, am Anfang alle Variablen auflisten, damit ich immer nachschauen kann was sie bedeuten und bei welcher Variablen Nummer ich eigentlich grad bin. Function könnte ich verwenden, habe ich jetzt aber nicht, Script funktioniert trotzdem nicht besser oder schlechter. Und die Variablen will ich auch absichtlich nicht mit Namen benennen, weil ich hatte ganz am Anfang als ich anfing Scripte zu schreiben das Problem dass ich dann nicht mehr wusste welchen genauen Namen ich verwendet hatte, ob jetzt zB Hauptordner, oder Startordner, oder Anfang. Einfach bei anderen Wörter. Deshalb alles mit a1, a2, ... e1, e2, ... und kommentiert, damit ich alles beieinander habe und der Reihe nach nachschauen kann. user_unknown Im Code fehlt ein fi.
Dieser Teil ist auch unfertig, ich hatte da angefangen eine Überarbeitung hinein zu schieben, nachher hätte ich das was unten gekommen wäre noch löschen müssen. Bin aber ja jetzt noch nicht weiter. user_unknown Variablen deklarieren, die man nur einmal nutzt, das auch noch 200 Zeilen später, ist keine gute Idee.
Als vertical Space nimmt man zur Gliederung entweder 1 oder 0 Zeilen Abstand. Mit 3, 4, 5 Zeilen etwas ausdrücken zu wollen, ist Quatsch. Wahrscheinlich fehlt da eine benannte Funktion.
So beim ersten Drübersehen.
Es gibt auch keinen plausiblen Grund, Variablen, die nichts miteinander zu tun haben, a1, a2, a3 zu nennen.
Die Variablen a3 und a4 werden gar nicht verwendet. Leider meckert das Shellcheck nicht an. Wie viele gibt es noch?
Arduinoport 1 und 2 heißen bei Dir a2 und a10 - welchem Plan folgt das? Wieso nicht port1 und port2?
Ist eigentlich auch alles schon erklärt, ich mache es halt einfach so, das ist meine Logik und Plan, du verstehst es nicht gut wenn du nicht meine Absicht gehabt hast und das Script von Anfang an selbst geschrieben hast, auf die Art und weise wie ich das mache, mit all meinen Gedankengängen. Ich habe es halt einfach so gemacht, das ist wie wenn jemand ein Bild malt, und du fragst wieso hältst du den Schreiber so und nicht so, macht halt jeder wie es im grad am meisten gefällt. Und das mit den Abständen überall bei while habe ich auch einfach so gemacht, bin mir nicht ganz sicher was besser lesbar ist für mich. Habe am Anfang mal absichtlich den Abstand wieder entfernt weil es irgendwie leslicher ausgesehen hat ohne überall noch Abstände, sonder mit ##### Blöcken, das geht irgendwie besser wenn man immer hoch scrollt und eine weitere Variable hinzufügt, dann wieder runter an die richtige Stelle, dachte ich jedenfalls grad. Und wenn ich irgendwo wieder ein while entfernen muss oder hinzufüge kann ich überall wieder Abstände einfügen oder entfernen, scheint mir sehr mühsam... Und mit vergessenen done's hatte ich eigentlich auch nie Probleme, eher mit vergessenen fi's früher. Ich habe bei dem Problem mit dem zu langsamen "print $(printf 3 stellig)" jetzt eine Idee, es wäre zwar viel einfacher wenn das irgendwie schnell gehen würde auf die Art, aber irgendwie tut es das halt einfach nicht, und ich könnte auch einfach mit "if [ kleiner als 10 ], [ kleiner als 100 ], else" noch Nullen einfügen, und es zwischenzeitlich nochmals in einer Variable speichern. Das sollte schneller gehen, etwa 0.01s glaube ich, was gerade etwa im Rahmen liegt. Weis nur nicht wie viel die eigentliche Prozent Rechnung dauert, dürfte dann auch nicht mehr all zu lange gehen. Und da die 2 Stellige Zahl nur die Nummern von den Servos oder Sensoren sind, und sich nicht verändern, könnte ich die in ein Array schreiben, dann brauche ich nur if's für die letzte 3 stellige Zahl im 6er Block den die Arduinos erhalten. Das Probiere ich demnächst aus...
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11176
Wohnort: München
|
ka111 schrieb: Aber könnte man den zB den printf Befehl dazu benutzen um 1 Zahl auszugeben, dann direkt eine immer 2 Stellige angehängt, dann nochmals eine immer 3 stellige, dann einen Doppelpunkt, und wieder von vorne? Ohne eben "printf 1$(printf 2 stellig)" zu nutzen? Also nur ein einziges mal printf am Anfang, und nur gewisse Zahlen in 3 stellige umwandeln?
Klar, du kannst da mehrere Formatierungsplatzhalter einbauen - also z.B. wenn man jedes Argument mit führenden Null und gefolgt von einem Zeilenumbruch haben will:
$ printf "%02d\n" 5 10 2 4
05
10
02
04
Oder wenn man die Argumente nach einem bestimmten Muster kombinieren will:
$ printf "%d%03d:" 5 10 2 4 # Achtung, da gibt es keinen Zeilenumbruch am Ende der Ausgabe
5010:2004:
Das funktioniert auch mit Arrays:
$ myArray=(5 10 2 4)
$ printf "%d%03d:" "${myArray[@]}"
5010:2004:
|
ka111
(Themenstarter)
Anmeldungsdatum: 22. Juni 2014
Beiträge: 141
|
Ja genau das ist es ja!! Das ist mir gar nicht aufgefallen das man vor und nach das %03d auch noch etwas hinschreiben kann, auch Variablen oder Arrays. Dann wäre die (von Hand aufgeführte) Lösung: declare -A a
a[1]=01 # Servo / Sensor Nr.
a[2]=02 # Servo / Sensor Nr.
a[3]=03 # Servo / Sensor Nr.
b1=1 # ausgerechneter Winkel Prozent Wert
b2=18 # ausgerechneter Winkel Prozent Wert
b3=180 # ausgerechneter Winkel Prozent Wert
printf "1${a[1]}%03d:1${a[2]}%03d:1${a[3]}%03d" $b1 $b2 $b3 > /dev/ttyUSB0 Und wenn ich den printf Befehl auf 50 6er Blöcke erweitere dauert das 0.03s 😀 Ich muss es einfach von Hand jedes mal erweitern wenn ich einen weiteren Sensor und Servo anfüge, aber wenn es wirklich nur 1 einziges Mal zusätzlich ist, ist das ok für mich. Das andere was ich probieren könnte ist mit if's Nullen einfügen, aber ich versuche dann einfach mal alles umzuschreiben und schaue was grad wie passend ist.. Danke vielmals für alle Hilfe hier (-:
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17548
Wohnort: Berlin
|
ka111 schrieb: Ou shit, du hast das ganze Script durchgesehen und verbessert! Ich danke dir wirklich vielmals, aber es funktioniert doch gar nicht mehr richtig...
Tja, nicht ganz ausgeschlossen, dass ich etwas verschlimmbessert habe, ich konnte es ja nicht vorher/später testen. Beabsichtigt war, keine Änderung zu machen, die eine Änderung bewirkt, sondern reines Refactoring in Richtung besserer Stil, Übersichtlichkeit, Verständlichkeit. Die einzig komplexe Stelle, was Du Hauptscript nennst, hatte ich noch nicht richtig erreicht und nur minimal darin geändert.
Ich muss das halbe Script wieder umschreiben, der ganze Abschnitt im Hauptscript funktioniert gar nicht mehr, und oberhalb davon muss ich wegen dem "warten bis der Arduino Rückmeldung gegeben hat" nochmals schauen, weil ich da etwas geändert habe auf dem Arduino gibt er keine Rückmeldung mehr einfach so.
Wo das fi hingehört, da habe ich einfach geraten. Statt
| wc -l file | cut -d" " -f1
|
Kannst Du
benutzen - der berühmte Fall, wo der Spruch "useless use of cat" nicht passt, weil wc, wenn man ihm nicht verrät, dass das aus einer Datei kommt, den Namen nicht erraten kann, und weglässt, so dass man ihn nicht wieder rausoperieren muss - es ist mir ein Rätsel, wieso wc keine Option hat, die Benennung des Ergebnisses wegzulassen. Für numerische Vergleiche solltest Du immer das if mit doppelt-runden Klammern verwenden. Aus:
| if [ "$(wc -l $speicher/speicher3 | cut -d" " -f1)" -lt $grenzwert ]
then
sleep 0.001
else
break
fi
|
wird so
| if (( $(cat $speicher/speicher3 | wc -l) <= grenzwert ))
then
sleep 0.001
else
break
fi
|
user_unknown Dass da bei WartenAufArduino2 3x fast das gleiche passiert, das muss einem doch auffallen! Da übergibst Du einer Funktion einen Paramter, der dann in der Funktion als $1 (, $2, $3) zur Verfügung steht. Da benennt man den entsprechend und kann die Funktion wiederverwenden. Wenn man eine Verbesserung hat, muss man sie nur 1x schreiben, nicht 3x.
Ich kenne $1, $2, $3 nicht, ich hatte vor etwa 2 Tagen das kurz angeschaut, und bin grad nicht draus gekommen... Ich weiss nicht einmal was mit Parameter eigentlich genau gemeint ist.
Wenn Du eine Funktion oder ein Programm aufrufst, dann unterscheidet man die Parameter nach ihrer Position. | echo foo bar 3 "4 und Ende"
|
Funktion oder Programm ist "echo", die Parameterzahl ist 4, der erste ist $1 (foo), der zweite $2 (bar), der dritte $3 ist hier 3 und der 4. ist "4 und Ende" $4.
Ich bin aber nicht sicher wie du das meinst, denkst du ich versuche die gleiche Variable 3x zu holen? Der Arduino hat bevor ich etwas darauf geändert hatte immer 0 gesendet wenn er den Befehl ausgeführt hat, und ich wartete bis jetzt meistens bis ich diese Rückmeldung erhalten habe, bin eben gar nicht mehr sicher ob ich das jetzt in diesem Script überhaupt brauche, ich muss es nochmals anschauen, es ist ja nicht im Zeitkritischen Bereich.
Nein, nicht 3x die gl. Variable holen. Du hast 3 Codeblöcke gehabt, 2 davon mit einer 11, das ist die Zeilenzahl von Arduino2, die überschritten werden soll. Beim 3. Mal nur 3.
user_unknown Eigentlich sieht es gar nicht so schlecht aus, es ist einfach komplex aufgebaut,
Nein, es ist planloses copy-paste mit einer Pseudoordnung, alle Variablen oben erst mal feierlich zu kommentieren, weit über die Hälfte davon gar nicht zu benutzen, eine Zählvariable e3 zu nennen und alle Nase lang wiederzuverwenden, als hätten diese e3s irgendwas miteinander zu tun.
Das stimmt, vieles wurde 1x gemacht und dann immer wieder kopiert und eingefügt, aber nicht planlos. Alle Variablen will ich oben auflisten, damit ich weiss bei welcher Variable ich eigentlich schon wieder bin.
Deswegen musst Du immer oben schauen. Und weil die Variablen keinen sinnvollen Namen haben. Und um Wegwerfvariablen wie Schleifenzähler unnötiges Gewese gemacht wird. Feierliche Initialisierung, Kommentierung.
Und es kann auch sein das nicht alle genutzt werden, bin nicht mehr sicher ob ich nicht aus dem vorherigen Script einfach alle in dieses neue hineinkopiert habe, aber nur wenige Teile des Scriptes dann auch wieder hinein kopiert habe. Und gewisse von den ersten 10, 15 a Variablen werden gar nicht gebraucht in diesem Script, zB der Port vom 1. Arduino wird nur in dem sehr kurzen anderen Script gebraucht das den Arduino startet, sonst eigentlich nicht. Aber ich wollte alle Variablen bei jedem Script wieder einfügen (von den a), damit ich wenn ich von irgendwo einen Teil heraus kopiere er auch im anderen funktioniert, wegen den Pfaden, und auch damit ich es einfach habe den Pfad zu ändern falls ich mal den Ordner verschiebe, und nicht dann in jedem Script überall alles durchsuchen muss wo der veraltete Pfad überall benutzt wurde. Und das mit den e1, e2, e3 ..., das mache ich halt so, ich brauche eine Variable für irgend etwas, dann die nächste, dann wieder die nächste. Ausser mir fällt auf das ich sie gut mehrmals verwenden kann, weil sie eben nur ein while Zähler ist.
Du kannst ja alle aus einer Sammlung herauskopieren am Anfang, aber dann lösch alle, die Du nicht brauchst, oder kommentiere sie aus. Beim Nachdenken über den Code muss man die alle im Kopf behalten - das schafft man nicht. Bei 5-7 Variablen ist normalerweise Schluss. Variablen, die man nicht sieht, über die kann man sich nicht unnötig Sorgen machen. Wenn eine Variable wiederverwendet wird, dann lohnt es sich auch, ihr einen guten Namen auszusuchen. Du kannst Variablen und Codeschnipsel, die immer wieder brauchst, in ein Script auslagern, das Du dann einliest, wenn Du es brauchst (wie, wahrscheinlich, warteAufArduino2) :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 | #!/bin/bash
#
# arduinofun.sh
# Arduinofunktionen
#
hauptordner="/pfad/zum/hauptordner"
speicher="$hauptordner/speicher"
warteAufAdruino2 () {
grenzwert=$1
while true
do
if (( $(cat $speicher/speicher3 | wc -l) <= grenzwert ))
then
sleep 0.001
else
break
fi
done
}
#
# ...
#
|
Und nutzt es dann so:
1
2
3
4
5
6
7
8
9
10
11
12 | #!/bin/bash
#
# Arduinofunktionen:
#
# Das Hilfsscript mit den Toolfunktionen einbinden:
source arduinofun.sh
warteAufAdruino2 11
# ...
warteAufAdruino2 3
# ...
|
Dann kannst Du die Ordnerstruktur tatsächlich ändern, in dem Du das nur in einer Datei an einer Stelle änderst. user_unknown Du weißt in 6 Monaten auch nicht mehr, das a2 port1 und a10 port2 ist.
Ja das stimmt, ich weis es auch meistens schon beim nächsten mal wenn ich den Pfad brauche nicht mehr, deshalb liste ich oben alles auf und habe in einem 2. Terminal den Anfang des Scriptes damit ich nachschauen kann welche Variable das ich jetzt brauche. Ist immer noch besser als wenn sich ein Pfad ändert den überall in jedem Script zu suchen. Ausser man würde es mit grep oder so suchen oder gleich mit sed ersetzen...
Ein aussagefähiger Name ist da viel besser. Wenn Du Angst hast, die Länge des Variablennamens hätte einen Einfluss, miss es nach.
user_unknown Schleifen, die eine bestimmte Zahl an Durchläufen absolvieren, schreibt man mit einer for-loop, dafür wurde sie gemacht
Aha ok, gut zu wissen. Aber ich habe nie nachgeschaut wie eine for loop funktioniert, hatte das vor Jahren am Anfang mal angeschaut, und bin grad nicht draus gekommen und hatte auch nie einen Grund etwas anderes als eine while Schleife zu verwenden. Auch das while read line kannte ich bis zum Hauptscript nicht, ich musste noch nie jede Zeile einer Datei durchsuchen, nur bestimmte Zeilen, die ich mit sed -n Xp herausgesucht hatte.
Mit "draus gekommen" meinst Du "drauf gekommen"?
user_unknown Für den Zähler verwendet man immer ein frisches i, evtl. ein n oder x, bei verschachtelten Schleifen auch mal ein j. Aber nicht e3, das in keiner Beziehung zu e2 oder e4 steht. Man kommentiert nicht, dass man das hochzählt.
😀 Ich bin ja auch nicht im schön schreiben, ist doch egal wie ich das nenne, hauptsache ich komme draus 😀 wie gesagt, ich schreibe es ja nicht für jemand anderen, nur für mich, war keine Absicht dass das jemals jemand anderes sieht.
Wie Du siehst passiert es unversehens. Und was andere erfunden haben, etwa for-loops, haben sie selten aus Übermut erfunden. Eine for-loop drückt unmittelbar aus, dass eine Aktion eine bestimmte Anzahl Male wiederholt werden soll. Eine Zählvariable, die außerhalb der while-Schleife deklariert wird, wirkt, als müsse der Wert auch außerhalb und später bekannt sein, sprich, man muss sie beim Analysieren des Codes im Kopf behalten. Die Shell erlaubt leider keine Beschränkung der Sichtbarkeit von Variablen, aber man verschlimmert es, wenn man Variablen weit vor dem Gebrauch initialisiert.
user_unknown Nicht so gut ist die durchgängige Kleinschreibung. Im Gegensatz zu vielen anderen Sprachen ist die Wortstellung im Deutschen in Sätzen sehr variabel. Deswegen hilft Groß-Kleinschreibung beim Lesen.
user_unknown Solche Zeilen kommen mit wechselndem Wert statt 3p häufig vor. Sowas gehört auch in eine Funktion.
Zeile x soll aus der Datei speicher3 gelesen, und um alles, was keine Ziffer ist, gekürzt werden.
Das kann sed, dann braucht man nicht 2 externe Programme aufzurufen:
Ich könnte tatsächlich gewisse Teile des Scriptes in einen function Befehl packen, damit ich einen besseren Überblick habe über den Ablauf. Aber ich habe auf eine Art angefangen und es dann nicht gemacht, und letzten Endes ist dann halt einfach die Unübersicht bei allen Funktionen, anstatt im ganzen Script, was aber etwas besser sein könnte. Kann ich mir am Schluss nochmals überlegen ob ich das machen will. Und sed ist der Befehl den ich am wenigsten mag, wegen der Darstellung mit allen Sonderzeichen. Ich komme bei sed nie draus, deshalb vermeide ich es wann immer möglich. Nur sed -i und sed -n Xp scheint mir einfach verständlich.
| sed -n "$zeile s/[^0-9]//g; $zeile p" $speicher/speicher3
|
Das sed -n "Befehl(e)" DATEI kennst Du ja schon. "$zeile s/MUSTER/ERSETZUNG/gp" bedeutet, dass nach dem Muster MUSTER gesucht werden soll, und dieses durch ERSETZUNG (in unserem Fall: nix) ersetzt werden soll (s:substitute). Das Muster ist die Gruppe der Ziffern 0-9, aber sie ist mit dem führenden Caret ^ negiert. Und dann kommt noch ein g für "global", sonst wird nur das erste Muster ersetzt. Und dann kam wohl der Fehler, wieso nichts mehr geklappt hat: das $zeile p für print hinter dem g hatte ich vergessen. Sorry. Ich habe aber keine Testdaten. Hier ein Testscript für die umgebaute Chose:
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70 | #!/bin/bash
echo " Mieser Kommentartrick
13
4
15
26
17
28
19
120
111
123
" > /dev/null
selbst=$0
liesZiffernAusZeile () {
zeile=$1
sed -n "$zeile s/[^0-9]//g; $zeile p" $selbst
}
declare -a f
initFotoSensor () {
for ((i = 1; i < 6; i+=1))
{
zeile=$(( i * 2 + 1 ))
f[$i]=$(liesZiffernAusZeile $zeile)
# echo "f[$i]=" ${f[$i]}
}
}
initFotoSensor
declare -a fotosensor
fotosensor=(${f[@]})
initFotoSensor
declare -a sensor
sensor=(${f[@]})
# Nur für Test relevant, da die Werte sonst immer gleich sind.
for ((i = 1; i < 6; ++i))
{
sensor[$i]=$((sensor[$i] + $((RANDOM%5 - 2 )) ))
}
# sensorwerteAufnehmen
echo fotosensor ${fotosensor[@]}
echo sensor ${sensor[@]}
# unterschied zwischen f und g ausrechnen
# i < e1 im Original
for ((i=1; i < 6; i+=1))
do
# wenn f < g, dann g-f und i=f, sonst umgekehrt
if (( f[i] < g[i] ))
then
# war h$i, i$i bzw. h$e1 oder e3, i$e1/e3
delta[$i]=$(( g[i] - f[i] ))
ii[$i]=${f[i]}
elif (( f[i] > g[i] ))
then
delta[$i]=$(( f[$i] - g[$i] ))
ii[$i]=${g[i]}
else
echo -e "\nERROR bei Nr. $i, f{[$i]}=${f[$i]} , g{[$i]}=${g[$i]}"
fi
# debug:
# echo ${delta[i]}":"${ii[i]}
done
|
Statt f und g würde ich ja vielleicht f und s benutzen - Fotosensor und Sensor, aus h und i wurden delta und ii, weil ich schon angefangen hatte e1 durch i zu ersetzen. So kurze Namen wie i, n, x sollte man nur für Wegwerfvariablen benutzen, die in einer Schleife benutzt und dann vergessen werden. Sehe ich das richtig, dass Sensorwerte aufnehmen das gleiche ist, wie Initfotosensor, nur mit zeitlichem Abstand und daher anderen Werten? Wieso sind gleiche Werte ein Error - kann das nicht vorkommen?
user_unknown Ohne zu schauen, ob es für Deinen Code relevant ist, lässt sich allgemein sagen:
Externe Programme aufzurufen (sed, wc, tr) dauert oft länger, als eine shellinterne Funktion aufzurufen. Die Shell ist aber nicht so mächtig, wie sed und Konsorten, das wäre der Punkt, wonach ich schauen würde, müsste ich das unter Zeitdruck beschleunigen, koste es was es wolle.
Das ist sehr gut zu wissen, danke. Aber ich glaube ich nutze sowieso nur einen Bruchteil von dem was Bash könnte. Aber könnte man den zB den printf Befehl dazu benutzen um 1 Zahl auszugeben, dann direkt eine immer 2 Stellige angehängt, dann nochmals eine immer 3 stellige, dann einen Doppelpunkt, und wieder von vorne? Ohne eben "printf 1$(printf 2 stellig)" zu nutzen? Also nur ein einziges mal printf am Anfang, und nur gewisse Zahlen in 3 stellige umwandeln?
Probier es aus
| printf "%02d%04d:%d%03d" 4 12 3 14
|
Ich scheue noch davor zurück, das Kauderwelsch am Skriptende zu analysieren. Und das ist ein starkes Indiz für unwartbaren Code: kryptischer Code mit geheimen Variablen, die verschachtelt durch echo/eval gejagt werden mit verbundener Quoteshölle.
user_unknown
Ist eigentlich auch schon erklärt, ich mach das halt eben einfach so,
Und vor Dir haben es andere auch einfach so gemacht, und gemerkt, dass man damit auf die Nase fällt, immer wiederr, wenn man es nicht ändert.
am Anfang alle Variablen auflisten,
Furchtbare Unsitte!
damit ich immer nachschauen kann was sie bedeuten und bei welcher Variablen Nummer ich eigentlich grad bin.
Weil sich niemand den Namen e4 merken kann, logisch. Und weil die Variable nicht da steht, wo sie gebraucht wird.
Function könnte ich verwenden, habe ich jetzt aber nicht, Script funktioniert trotzdem nicht besser oder schlechter. Und die Variablen will ich auch absichtlich nicht mit Namen benennen, weil ich hatte ganz am Anfang als ich anfing Scripte zu schreiben das Problem dass ich dann nicht mehr wusste welchen genauen Namen ich verwendet hatte, ob jetzt zB Hauptordner, oder Startordner, oder Anfang.
Ja, man pickt nicht beim ersten Versuch den besten Namen. Dann überlege, welcher Name der beste ist, und verwende den, bis Du Dich anders entscheidest. Anfang ist schon mal ein schlechter Anfang. Anfänge gibt es so viele im Programm.
Einfach bei anderen Wörter. Deshalb alles mit a1, a2, ... e1, e2, ... und kommentiert, damit ich alles beieinander habe und der Reihe nach nachschauen kann.
Du kannst oben eine Kommentarsektion mit allen Namen machen, Wenn Du den Code aufräumst sind es auch nicht mehr 400 Zeilen, sondern nur noch 3, 4 Bildschirmseiten und die Variablen tauchen erst da auf, wo sie gebraucht werden. user_unknown Variablen deklarieren, die man nur einmal nutzt, das auch noch 200 Zeilen später, ist keine gute Idee.
Als vertical Space nimmt man zur Gliederung entweder 1 oder 0 Zeilen Abstand. Mit 3, 4, 5 Zeilen etwas ausdrücken zu wollen, ist Quatsch. Wahrscheinlich fehlt da eine benannte Funktion.
So beim ersten Drübersehen.
Es gibt auch keinen plausiblen Grund, Variablen, die nichts miteinander zu tun haben, a1, a2, a3 zu nennen.
Die Variablen a3 und a4 werden gar nicht verwendet. Leider meckert das Shellcheck nicht an. Wie viele gibt es noch?
Arduinoport 1 und 2 heißen bei Dir a2 und a10 - welchem Plan folgt das? Wieso nicht port1 und port2?
Ist eigentlich auch alles schon erklärt, ich mache es halt einfach so, das ist meine Logik und Plan, du verstehst es nicht gut wenn du nicht meine Absicht gehabt hast und das Script von Anfang an selbst geschrieben hast, auf die Art und weise wie ich das mache, mit all meinen Gedankengängen. Ich habe es halt einfach so gemacht, das ist wie wenn jemand ein Bild malt, und du fragst wieso hältst du den Schreiber so und nicht so, macht halt jeder wie es im grad am meisten gefällt.
Je nach Stift oder Pinsel gibt es auch ungünstige und günstige Stifthaltungen. Ein Rechtshänder mag einem Linkshänder keine guten Tipps geben können, aber ein etwas älterer Hase blickt eben geläutert auf die Fehler seiner Jugend zurück.
Und das mit den Abständen überall bei while habe ich auch einfach so gemacht, bin mir nicht ganz sicher was besser lesbar ist für mich. Habe am Anfang mal absichtlich den Abstand wieder entfernt weil es irgendwie leslicher ausgesehen hat ohne überall noch Abstände, sonder mit ##### Blöcken,
Hast Du kein Syntaxhighlightening? Welchen Editor benutzt Du?
das geht irgendwie besser wenn man immer hoch scrollt und eine weitere Variable hinzufügt, dann wieder runter an die richtige Stelle, dachte ich jedenfalls grad.
Ja, so zieht eine Unsitte die nächste nach sich. Kommentarzeichenblöcke, weil man die Variablen bei Adam & Eva stehen hat und scrollen muss, bis der Arzt kommt.
Ich habe bei dem Problem mit dem zu langsamen "print $(printf 3 stellig)" jetzt eine Idee, es wäre zwar viel einfacher wenn das irgendwie schnell gehen würde auf die Art, aber irgendwie tut es das halt einfach nicht, und ich könnte auch einfach mit "if [ kleiner als 10 ], [ kleiner als 100 ], else" noch Nullen einfügen, und es zwischenzeitlich nochmals in einer Variable speichern.
Das ganze eval-Gelumpe kommt weg und verschachtelte prints sind auch keine Option.
Das sollte schneller gehen, etwa 0.01s glaube ich, was gerade etwa im Rahmen liegt. Weis nur nicht wie viel die eigentliche Prozent Rechnung dauert, dürfte dann auch nicht mehr all zu lange gehen. Und da die 2 Stellige Zahl nur die Nummern von den Servos oder Sensoren sind, und sich nicht verändern, könnte ich die in ein Array schreiben, dann brauche ich nur if's für die letzte 3 stellige Zahl im 6er Block den die Arduinos erhalten.
So sieht das überarbeitete Skript aus, bis Zeile 175 von 240:
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243 | #!/bin/bash
hauptordner="/pfad/zum/hauptordner"
speicher="$hauptordner/speicher"
port1="/dev/ttyUSB0"
port2="/dev/ttyUSB1"
d1=01 # photosensor 1
d2=02 # photosensor 1
d3=03 # photosensor 1
d4=04 # photosensor 1
d5=05 # photosensor 1
# d6=06 # photosensor 1
# e1=6 # anzahl photosensoren
pause=5 # verzögerungszeit
e3=1 # aktuellem photosensor variabel zahl für schleife
e5=301000 # erster sensor abfrage befehl, für auflistung aller arduino2 befehle in einem satz
# e6=101000 # variable für servo befehle zusammen an arduino senden
# alle j variable sind für servo winkel befehl an arduino1 senden
arduinoVerbinden () {
echo ""
echo "verbinde 2. arduino"
pfad/zum/script* # 2. arduino verbinden
sleep 3
echo 000000 > $port2 # weil nach Neustart vom Arduino die erste Rückmeldung alles überschreibt, sonst stimmt die Reihenfolge nicht
sleep 1 # sleep zeit zu erster start obige zeile
echo ""
echo "fertig"
}
# warten bis 2. arduino speicher alle zeilen erhalten hat, und fertig
warteAufAdruino2 () {
grenzwert=$1
while true
do
if (( $(cat $speicher/speicher3 | wc -l) <= grenzwert ))
then
sleep 0.001
else
break
fi
done
}
aufnahmeSensorWerteMinMax () {
# aufnahme der sensor werte min und max
echo "beginne"
echo "min start"
echo "erfasse werte"
sleep $pause
echo "0" > $speicher/speicher3 # arduino Kommunikationsspeicher leeren
echo 3"$d1"000 > $port2
echo 3"$d2"000 > $port2
echo 3"$d3"000 > $port2
echo 3"$d4"000 > $port2
echo 3"$d5"000 > $port2
}
# [^0-9] löschen, weil noch unsichtbare zeichen a sind
liesZiffernAusZeile () {
zeile=$1
sed -n "$zeile s/[^0-9]//g; $zeile p" $selbst
}
sensorzahl=6
declare -a f
liesFotoSensor () {
for ((i = 1; i < sensorzahl; i+=1))
{
zeile=$(( i * 2 + 1 ))
f[$i]=$(liesZiffernAusZeile $zeile)
# echo "f[$i]=" ${f[$i]}
}
}
initMeldung () {
minmax=$1
aktion=$2
echo
echo "${minmax}-"Werte aufgenommen
echo
echo "max start"
echo "$aktion"
sleep $pause
}
# arduino Kommunikationsspeicher leeren
komSpeicherLeeren () {
echo "0" > $speicher/speicher3
echo 3"$d1"000 > $port2
echo 3"$d2"000 > $port2
echo 3"$d3"000 > $port2
echo 3"$d4"000 > $port2
echo 3"$d5"000 > $port2
}
arduinoVerbinden
aufnahmeSensorWerteMinMax
warteAufAdruino2 11
# initPhotoSensor
liesFotoSensor
declare -a fotosensor
fotosensor=(${f[@]})
initMeldung "min" "erfasse Werte"
komSpeicherLeeren
warteAufAdruino2 11
# sensorwerteAufnehmen
liesFotoSensor
declare -a sensor
sensor=(${f[@]})
initMeldung "max" "erfasse Werte"
echo "0" > $speicher/speicher3 # arduino kommunikations speicher leeren
echo 3"$d1"000 > $port2
warteAufAdruino2 3
# alle min sensor werte aufnehmen in f variablen, tr weil noch unsichtbare zeichen da sind
f6=$(liesZiffernAusZeile 3)
initMeldung "min" "nehme Werte auf"
# arduino kommunikations speicher leeren
echo "0" > $speicher/speicher3
echo 3"$d1"000 > $port2
warteAufAdruino2 3
# alle min sensor werte aufnehmen in g variablen, tr weil noch unsichtbare zeichen da sind
g6=$(liesZiffernAusZeile 3)
echo
echo "alle werte aufgenommen"
echo
### vor rechnen für haupt script
echo
echo "berechne..."
# alle g variablen sind für photosensor wert aufnahme max reserviert, gleiche anordnung wie d variablen
# alle h variablen sind für differenz zwischen f und g
# alle i variablen sind für + oder -, bei differenz zwischen f und g, wird nur i=f oder g gesetzt
declare -a delta
declare -a ii
# unterschied zwischen f und g ausrechnen
# i < e1 im Original
for ((i=1; i < sensorzahl; i+=1))
do
# wenn f < g, dann g-f und i=f, sonst umgekehrt
if (( f[i] < g[i] ))
then
# war h$i, i$i bzw. h$e1 oder e3, i$e1/e3
delta[$i]=$(( g[i] - f[i] ))
ii[$i]=${f[i]}
elif (( f[i] > g[i] ))
then
delta[$i]=$(( f[$i] - g[$i] ))
ii[$i]=${g[i]}
else
echo -e "\nERROR bei Nr. $i, f{[$i]}=${f[$i]} , g{[$i]}=${g[$i]}"
fi
# debug:
# echo ${delta[i]}":"${ii[i]}
done
# Sensorbefehlsabfrage in einem Satz ausrechnen
# e3=2 # variable auf passenden wert zurücksetzen für while
# while [ $e3 -le $e1 ]; do
# e5="$e5":3"$(eval 'echo $d'$e3)"000
# ((e3+=1))
# done
for (( i=2; i <= e1; i+=1))
do
e5="$e5":3"$(eval 'echo $d'$i)"000
done
echo
echo "fertig"
### haupt script
# vorgängig
echo "0" > $speicher/speicher3 # arduino kommunikations speicher leeren
sed -i '1d' $speicher/speicher3 # einzige zeile aus speicher3 löschen
echo "$e5" > $port2 # vorgängige sensor wert abfrage
while true
do
echo "$e5" > $port2 # sensor wert abfrage
e3=1 # variable zurücksetzen für while
while read -r line; do # while read = if arduino speicher (speicher3) > 50 (e3) zeilen
if [ $e3 = 1 ]; then
eval 'j'$e1=$line # rechnung
fi
((e3+=1))
done < $speicher/speicher3
e3=1 # variable zurücksetzen, variablen zahl aufzählung für while
echo "0" > $speicher/speicher3 # arduino kommunikations speicher leeren
while [ $e3 -le $e1 ]; do
echo 3"$(eval 'echo $d'$e3 )"000 > $port2 ################################### <--- dieser befehl muss von hand aufgezählt werden ohne schleife mit / zwischen zahlen
e3=$(($e3+1)) # aufzählungsvariable +1
echo "send"
date +%S.%N
echo 3"$(eval 'echo $d'$e3 )"000
done
#echo "send"
#date +%S.%N
# sensor werte aus arduino speicher lesen, in prozent umwandeln und winkel befehl senden
e3=3 # variable zurücksetzen auf erste zeile von sensor wert aus arduino speicher, variablen zahl aufzählung für while
# wenn aktueller sensor/winkel max anzahl an sensoren/winkel überschreitet, *2 +1 weil asl erstes 0 zum überschreiben geschrieben wird, und dann 2 zeilen für jeden sensor wert (0 antwort, und wert)
while [ $e3 -le $((e1*2+1)) ]
do
echo "empfang"
date +%S.%N
# sensor wert in variable speichern aus 2. arduino speicher, tr weil unsichtbare zeichen sonst vorhanden sind
e4=$(liesZiffernAusZeile $e3)
echo " $e4"
#echo "1"$(eval 'echo $d'$(($(($e3-1))/2)) )
#echo $(printf "%03d\n" "$(($(( 180000000/$(eval 'echo $h'$(( $(($e3-1)) /2)) ) * $(($e4 - $(eval 'echo $i'$(( $(($e3-1)) /2)) ) )) )) /180000))")
echo "befehl: $(echo "1"$(eval 'echo $d'$(($(($e3-1))/2)) )""$(printf "%03d\n" "$(($(( 180000000/$(eval 'echo $h'$(( $(($e3-1)) /2)) ) * $(($e4 - $(eval 'echo $i'$(( $(($e3-1)) /2)) ) )) )) /1000000))")"" )"
# rechnen und winkel befehl senden, printf weil nur so ist winkel zahl immer 3 stellig
echo "1"$(eval 'echo $d'$(($((e3-1))/2)) )""$(printf "%03d\n" "$(($(( 180000000/$(eval 'echo $h'$(( $((e3-1)) /2)) ) * $((e4 - $(eval 'echo $i'$(( $((e3-1)) /2)) ) )) )) /1000000))")"" > $port1
((e3+=2))
done
#echo "empfang"
#date +%S.%Nc
done
killall cat # cat wegen 2. arduino beenden
$hauptordner/scripte/2.* # 1. arduino wieder verbinden und cat neu starten
|
Stimmen diese Kommentare eigentlich?
| d1=01 # photosensor 1
d2=02 # photosensor 1
d3=03 # photosensor 1
d4=04 # photosensor 1
d5=05 # photosensor 1
# d6=06 # photosensor 1
|
Die Werte werden an keiner Stelle im Script verändert. Was soll das, also?
|
ka111
(Themenstarter)
Anmeldungsdatum: 22. Juni 2014
Beiträge: 141
|
user_unknown Statt "wc -l file | cut -d" " -f1" Kannst Du "cat file | wc -l"
Das hatte ich sogar irgendwann dann mal per Zufall irgendwo gesehen, man kann auch wc -l < /Pfad/Datei machen. Ob das jetzt nicht genau gleich ist wie mit cat weiss ich nicht, aber sah für mich so aus als ob man das cat ganz weg lässt, weiss nicht genau wie das im Hintergrund läuft mit einfach nur <. Aber ich kannte es am Anfang auch noch nicht, weis grad nicht wo du das gesehen hast mit cut, wahrscheinlich irgendwo am Anfang, oberhalb des Haupt Scriptes.
Für numerische Vergleiche solltest Du immer das if mit doppelt-runden Klammern verwenden.
Also ich könnte dazu jetzt wieder etwas fragen, aber es ist auch nicht zwingend nötig das jetzt auch noch zu diskutieren. Mal abgesehen davon dass ich nicht wirklich weiss was genau im Hintergrund anders passiert mit zwei Klammern, braucht es zwei damit man anstatt -lt ein < benutzen kann? Ich hatte und habe das Problem dass ich manchmal eine Differenz bekomme die im minus Bereich liegt, wenn eben zB der min_Wert nicht kleiner als der max_Wert ist, was eben auch nicht vorherbestimmt ist, es kann auch in die andere Richtung gehen. Trotzdem muss ich manchmal nur wissen, ist die Differenz grösser als zB 50? Und das kann ich schlecht rechnen, wenn ich nicht weiss ob die Differenz im minus Bereich liegt. Deshalb bin ich dann irgendwann darauf gekommen das man < oder > dafür verwenden kann anstatt -lt oder -gt, und dann sollte es egal sein ob es -20 oder +20 sind. Es hat dann aber irgendwie doch nicht richtig funktioniert und ich bin wieder dazu über gegangen einfach mit if vorher zu fragen. Also es geht auch so, ausser du könntest mich jetzt grad kurz erleuchten, wie ich "if [ (plus oder minus Zahl) grösser als (50, egal ob -50 oder +50) ]; then ..." mache?
Wenn Du eine Funktion oder ein Programm aufrufst, dann unterscheidet man die Parameter nach ihrer Position. ... Funktion oder Programm ist "echo", die Parameterzahl ist 4, der erste ist $1 (foo), der zweite $2 (bar), der dritte $3 ist hier 3 und der 4. ist "4 und Ende" $4.
Aha, ok, danke für die ausführliche Erklärung. Ich bin mir zwar jetzt noch nicht sicher wie ich das verwenden soll, aber das müsste ich mal praktisch testen...
Nein, nicht 3x die gl. Variable holen. Du hast 3 Codeblöcke gehabt, 2 davon mit einer 11, das ist die Zeilenzahl von Arduino2, die überschritten werden soll. Beim 3. Mal nur 3.
Aha, das müsste dann eben bevor ich am Arduino etwas geändert hatte gewesen sein, als es noch zusätzlich zu jedem Wert immer 0 für "ausgeführt" zurück meldete, und dann wären (vielleicht -gt?) 11 Zeilen für die 6 bisherigen Sensoren, und 3 Zeilen wäre dann nur 1x das überschreiben mit 0 (weil wusste es irgendwann mal nicht besser), und die 2 fache Rückmeldung für irgend etwas das nur 1 Durchgang war auf dem Arduino, irgend einen Sinn hatte das sicher, es bedeutete warten bis Arduino fertig ist.
Du kannst ja alle aus einer Sammlung herauskopieren am Anfang, aber dann lösch alle, die Du nicht brauchst, oder kommentiere sie aus.
ja, irgendwann hätte ich das vielleicht gemacht, hatte nur grad keine Lust dazu, wenn ich das überhaupt gemacht hatte, wahrscheinlich wollte ich dann eben nur mal schnell testen und ein neues Script schreiben, dass dann wie immer viel grösser und länger wurde als gedacht.
Beim Nachdenken über den Code muss man die alle im Kopf behalten - das schafft man nicht. Bei 5-7 Variablen ist normalerweise Schluss. Variablen, die man nicht sieht, über die kann man sich nicht unnötig Sorgen machen. Wenn eine Variable wiederverwendet wird, dann lohnt es sich auch, ihr einen guten Namen auszusuchen.
Ich brauche aber einfach viel mehr als 10, manchmal werden es über 100 verschiedene, und min 90% wird wahrscheinlich auch wirklich gebraucht. Jetzt bei diesem Script waren es bisher erstaunlich wenig, fast keine, nur e2 - e6 die einfach aufgezählt werden und für irgend etwas gebraucht werden, normalerweise sind das eher 20 30, selten auch mal über 100. Deswegen denke ich kann ich das auch vergessen mit den guten Namen ausdenken. Und ich will es auch so machen mit so vielen Variablen, so komme ich mit Rechnen besser an den Punkt zu dem ich möchte, auch Dateien benenne ich manchmal nur noch mit Zahlen, damit ich gleich zum Namen komme durchs Rechnen. Ginge sicher auch anders, aber je nach dem ist es vielleicht sogar praktischer wenn es Zahlen sind, zB wenn es so etwas wie eine Karte werden soll, für irgend etwas ganz anderes. Am liebsten hätte ich ich bräuchte eigentlich nur noch Variablen und kann ein Script nur noch rechnerisch mit while und if und Variablen zusammen bauen, so dass ich immer durch die Rechnung gleich an dem Punkt bin wo ich sein will (wenn das jetzt noch verständlich ist)...
Du kannst Variablen und Codeschnipsel, die immer wieder brauchst, in ein Script auslagern, das Du dann einliest, wenn Du es brauchst (wie, wahrscheinlich, warteAufArduino2)
Ah das geht auch mit Dateien, das wusste ich nicht, danke. Wäre vielleicht noch praktisch manchmal, manchmal vielleicht auch besser direkt im Script. Aber ja, das könnte ich mir wirklich überlegen ob ich das nicht noch machen will, es wäre dann eben übersichtlicher im Ablauf vom Script, ich hatte es per Zufall jetzt einfach (noch) nicht gemacht (im Script).
Ein aussagefähiger Name ist da viel besser. Wenn Du Angst hast, die Länge des Variablennamens hätte einen Einfluss, miss es nach.
Habe ich gar noch nicht dran gedacht...
Schleifen, die eine bestimmte Zahl an Durchläufen absolvieren, schreibt man mit einer for-loop, dafür wurde sie gemacht
Aha ok, gut zu wissen. Aber ich habe nie nachgeschaut wie eine for loop funktioniert, hatte das vor Jahren am Anfang mal angeschaut, und bin grad nicht draus gekommen und hatte auch nie einen Grund etwas anderes als eine while Schleife zu verwenden. Auch das while read line kannte ich bis zum Hauptscript nicht, ich musste noch nie jede Zeile einer Datei durchsuchen, nur bestimmte Zeilen, die ich mit sed -n Xp herausgesucht hatte.
Mit "draus gekommen" meinst Du "drauf gekommen"?
Nein, ich meinte wirklich ich hatte es nicht verstanden, das war noch ganz am Anfang als ich anfing Scripte zu schreiben, ich denke ich würde es heute schnell verstehen (müsst mich jetzt aber nicht grad testen (-: ), da ich while read line auch verstehe, aber ich hatte einfach noch nie das Verlangen danach etwas anderes als die alte übliche while Schleife zu benutzen, die hat gut funktioniert. Könnte ich mir anschauen mit der for loop.
Eine Zählvariable, die außerhalb der while-Schleife deklariert wird, wirkt, als müsse der Wert auch außerhalb und später bekannt sein, sprich, man muss sie beim Analysieren des Codes im Kopf behalten. Die Shell erlaubt leider keine Beschränkung der Sichtbarkeit von Variablen, aber man verschlimmert es, wenn man Variablen weit vor dem Gebrauch initialisiert.
Das habe ich auch meistens im Kopf, das ich die Variable vielleicht auch ausserhalb der Schleife wieder brauche, ob es dann wirklich auch so ist sehe ich dann erst später. Ausser es ist jetzt wirklich nur eine reine Zählvariable, die nur genau für diese eine Schleife ist, ohne Verbindung zu irgend etwas anderem. Bei meinem Script sollte es aber glaube ich immer (oder meistens) eine Verbindung zu den d1 Variablen haben, die die Nummer von den Servos und Sensoren sind.
Das sed -n "Befehl(e)" DATEI kennst Du ja schon. "$zeile s/MUSTER/ERSETZUNG/gp" bedeutet, dass nach dem Muster MUSTER gesucht werden soll, und dieses durch ERSETZUNG (in unserem Fall: nix) ersetzt werden soll (s:substitute). Das Muster ist die Gruppe der Ziffern 0-9, aber sie ist mit dem führenden Caret ^ negiert. Und dann kommt noch ein g für "global", sonst wird nur das erste Muster ersetzt. Und dann kam wohl der Fehler, wieso nichts mehr geklappt hat: das $zeile p für print hinter dem g hatte ich vergessen. Sorry. Ich habe aber keine Testdaten.
Ah das geht auch mit durch nichts ersetzen... Diesen Befehl kenne ich auch, den habe ich in einer Notiz mit nützlichen Befehlen gespeichert, das ist immer mein "Zeile suchen und ersetzen" Befehl. Danke für die ausführliche Erklärung was das alles bedeutet bei diesem Befehl.
Statt f und g würde ich ja vielleicht f und s benutzen - Fotosensor und Sensor
ja wenns grad aufgeht mache ich das auch so, aber meistens geht es das nicht ganz und ich gehe einfach der Reihe nach, eben, sind meistens sehr viele Variablen, hier in diesem Script sind sie ja noch alle sehr kurz und übersichtlich.
Sehe ich das richtig, dass Sensorwerte aufnehmen das gleiche ist, wie Initfotosensor, nur mit zeitlichem Abstand und daher anderen Werten? Wieso sind gleiche Werte ein Error - kann das nicht vorkommen?
Es ist für mich jetzt sehr schwierig all diesen neuen Befehlen hinterher zu kommen, mit dem das ich mir noch etwas unsicher mit dem $0 bin, dem dazugehörigen Text im Script, der for schleife, die ich auch noch nicht nachgeschaut habe, und auch über den sed Befehl, mit den $0 $1, ohne das der sed Befehl scheinbar eine Eingabedatei bekommt? Ist das wirklich richtig, oder hast du da vielleicht auch mal die Eingabedatei vergessen? Egal, ich kann Dir jedenfalls ganz einfach sagen wieso Error wenn weitere Zahl: Der Arduino erwartet immer 6 Zahlen, plus ein 7. Zeichen, das entweder das End-Zeichen ist das sowieso immer mitgeschickt wird, oder einen Doppelpunkt. Und alle Zeichen die der Arduino erhält, erhält er ja sowieso als Zahl, man findet es heraus wenn man nach "ascii tabelle arduino" sucht, ich bin jetzt nicht ganz sicher aber ich glaube der Arduino erhält die ASCII Zahlen, und nicht die Zeichen die man auf der Tastatur hat, bin jetzt aber nicht ganz sicher ob das richtig genannt ist oder irgendwie umgekehrt oder anders. Jedenfalls erhält der Arduino immer eine Zahl für jeden Buchstaben, Zeichen oder Zahl. Und wenn ich das immer noch mit der richtigen Menge subtrahiere auf dem Arduino (weil die Zahl 0 als 48 ankommt), dann erhält der Arduino 0-9 auch als Zahl 0-9, einen Doppelpunkt erhält er als 10, und das automatische End-Zeichen (oder was das ist) erhält er als ca -38 oder so irgendwie. Deshalb frage ich nach -gt 9, oder -lt 0, weil wenn die 7. Zahl die der Arduino erhält wirklich eine Zahl ist, und nicht ein anderes Zeichen das niedriger oder höher 0 und 9 ist, dann stimmt irgend etwas mit der 6er Zahlenblock Reihenfolge nicht mehr, und es funktioniert alles nicht mehr. Aber das sollte nie passieren, vielleicht wenn ich von Hand "echo 6Zahlen" an den Arduino sende, und aus versehen 7 geschickt habe oder so. Hoffe du verstehst was ich meine, der Arduino erwartet 6 Zahlen + 1 Zeichen, wenn die 7. Stelle wieder eine Zahl ist stimmt die Reihenfolge nicht mehr.
Probier es aus: printf ...
Das habe ich schon, danke. Es funktioniert so wie im Code eine Antwort vor deiner letzten. Und ich meinte übrigens die Dauer solch eines printf Befehls mit 50 6er Zahlenblöcke, inklusive 3stelliger Variable, dauert nur 0.003s und nicht 0.03.
Und vor Dir haben es andere auch einfach so gemacht, und gemerkt, dass man damit auf die Nase fällt, immer wiederr, wenn man es nicht ändert.
Also ich falle im Moment nicht auf die Nase, habe ich jedenfalls das Gefühl. Meinen Probleme in diesem Script liegen ganz wo anders, dann am ehsten noch bei einem printf Befehl für 50 6er Zahlenblöcke mit Array und 3stelliger Variable darin, glücklicherweise ist alles durch : getrennt, sonnst wäre es sehr mühsam das zu durchblicken. Überhaupt habe ich eigentlich nur wirklich Probleme mit dieser (nicht mehr nötigen) Zeile aus dem alten Script: echo "1"$(eval 'echo $d'$(($(($e3-1))/2)) )""$(printf "%03d\n" "$(($(( 180000000/$(eval 'echo $h'$(( $(($e3-1)) /2)) ) * $(($e4 - $(eval 'echo $i'$(( $(($e3-1)) /2)) ) )) )) /1000000))")"" > $a2 # rechnen und winkel befehl senden Da habe ich absolut keine Überblick mehr darüber was gerechnet wird, ich sehe nur noch 2 Klammern auf, 1 zu, 1 auf 2 zu, paar andere Sonderzeichen... Die konnte ich nur grad knapp fertig stellen und wusste am Schluss nicht mehr was das ganze eigentlich schon wieder bedeutet, irgendwie hatte ich es auch mal schön kommentiert eine Zeile oberhalb, aber irgendwie sehe ich jetzt da auch nichts mehr schön kommentiert. Und ich mache es ja jetzt sowieso anders mit dem printf Befehl den ich schon als richtiges Beispiel aufgeschrieben habe. Und mir fällt auch auf das ich vielleicht nicht alles grad in einem Satz hätte rechnen müssen, und es dann auch übersichtlicher gewesen wäre. Also meine Probleme liegen ganz wo anders als Du sie im Moment siehst, das mit den Variablen Blöcke am Anfang und den nichts aussagenden Variablen Nummern macht mir kein Problem, kann ich so machen wenn ich will, hält mich nicht auf das Script zu schreiben, sehe auch nicht grad etwas das in allem besser ist und 10x schneller geht, wenn man eben bedenkt das ich sowieso auch Dateien manchmal nur noch mit Zahlen benenne (was sicher gar niemand eine gute Idee findet (-: ). Je nach Stift oder Pinsel gibt es auch ungünstige und günstige Stifthaltungen. Ein Rechtshänder mag einem Linkshänder keine guten Tipps geben können, aber ein etwas älterer Hase blickt eben geläutert auf die Fehler seiner Jugend zurück.
Ja das kann schon sein, Tipps sind sicher nicht schlecht. Aber vielleicht probiert man trotzdem lieber einfach mal frei drauf los, und nicht ganz genau nach Schema. Hauptsache ich bin glücklich beim scripten, nützt eine schöne Darstellung nichts wenn ich dauernd wieder (für mich gesehen) unnötigerweise Abstände lösche und einfüge kann für while done. Und wenn es zT. über 100 Variablen werden, und das immer noch gewünscht ist, ist das mit der Auflistung am Anfang auch nicht mehr so verkehrt, vielleicht.
Hast Du kein Syntaxhighlightening? Welchen Editor benutzt Du?
Ich weiss es nicht, ich benutze das was aufgeht wenn man auf einem normalen Ubuntu System editor im Terminal eingibt. Ich komme bei vielem nur minimal draus, ich mache einfach was ich machen kann, ohne mich immer über alle anderen möglichen Funktionen zu informieren, wenn sie nicht grad selbsterklärend sind.
Stimmen diese Kommentare eigentlich?
d1=01 # photosensor 1
d2=02 # photosensor 1
Ja das stimmt schon, die d Variablen werden hier nur dazu benutzt um die zwingend 2 stellige Servo/Sensor Nummer zu beinhalten. Diese werde ich jetzt in ein Array einfügen. Nur der Kommentar dazu stimmt natürlich nicht, es ist nicht immer der Sensor 1, sonder 1, 2 ... Das wurde kopiert und vergessen zu ergänzen. Edit: Ah nein, bei der Frage wegen der Error Meldung, das war im bash Script gar nicht weil der Arduino immer 6 Zahlen und 1 Zeichen erwartet, ich war irgendwie bei dem, weil auf dem Arduino gibt es das eben auch, aber von dort kommt ein Error wenn 7. Zahl nicht grösser 9 oder kleiner 0 ist. Du meinst wahrscheinlich den Punkt an dem ein Error (der einzige den ich jetzt grad mit grep gefunden habe im bash Script) ausgegeben wird, wenn min_wert und max_wert genau gleich gross sind, dann funktioniert die Rechnung nicht mehr, und sowieso, das sollte nicht möglich sein, dann ist etwas falsch gelaufen bei dem physischen Ablauf der Servos und Fotosensoren. Und genau dort ist eben auch das Problem mit dem evtl. minus Ergebnis der Differenz von min_wert und max_wert, deshalb diese if's dort.
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17548
Wohnort: Berlin
|
ka111 schrieb: user_unknown Statt "wc -l file | cut -d" " -f1" Kannst Du "cat file | wc -l"
Das hatte ich sogar irgendwann dann mal per Zufall irgendwo gesehen, man kann auch wc -l < /Pfad/Datei
Ja, mit Umleitung geht auch, gilt auch als eleganter, zeitlich nehmen die sich nichts - 0.003s bis 0.004s auch bei einer 0,5 MB Datei mit 3000 Zeilen.
Für numerische Vergleiche solltest Du immer das if mit doppelt-runden Klammern verwenden.
Also ich könnte dazu jetzt wieder etwas fragen, aber es ist auch nicht zwingend nötig das jetzt auch noch zu diskutieren.
Immer raus mit der Sprache!
Mal abgesehen davon dass ich nicht wirklich weiss was genau im Hintergrund anders passiert mit zwei Klammern, braucht es zwei damit man anstatt -lt ein < benutzen kann?
Ja, aber eine Konversion zu Betragsrechnung ist damit nicht verbunden. Bei einfachen Variablen, wie a, b und 7 kann man sich mit Mathe behelfen, wenn ein Zahlenüberlauf, wie bei Dir, ausgeschlossen ist: if (( a*a < 2500 )) ist ja das gleiche, wie (( $(betragVon a) < 50 )) . Aber wenn statt a eine komplizierte Berechnung da steht, müsste man die vor die Klammer ziehen und in einer Zwischenvariable abspeichern, oder die Rechnung 2x ausführen, was insbesondere dann heikel ist, wenn die Funktion einen Seiteneffekt hat, wie zum Beispiel die Zeile mit dem gelesenen Wert zu löschen.
Ob man Code einspart hängt also vom Einzelfall ab. Das Quadrieren schreit dann auch nach einem Kommentar. | absdiff () {
a=$1
b=$2
(( a < b )) && echo $((b-a)) || echo $((a-b))
}
absdiff 3 4
1
absdiff 4 3
1
|
Bestimmt sind Dir Kurzschluss-Und und KS-Oder nicht vertraut. Hier sind erst mal wieder die 2 Parameter, mit denen die Funktion aufgerufen wird a und b. Da es ein abstraktes, mathematisches Konzept ist, sind hier inhalslose Namen wie a und b in Ordnung. Der mathematische Ausdruck a < b kann wahr oder falsch sein. Das && ist die Verknüpfung 2er logischer Ausdrücke, wenn der erste falsch ist muss aber bei einer UND-Verknüpfung der zweite nicht ausgewertet werden (das Ergebnis bleibt so oder so falsch) und deswegen wird er beim Kurzschluss-& auch nicht ausgertet. Aber ein ODER-Ausdruck, bei dem der erste Teil falsch ist, ist noch nicht entschieden. Ist der erste Teil aber wahr, dann ist er unabhängig vom 2. Teil der ODER-Verknüpfung wahr, und der 2. Teil wird nicht ausgewertet. Das machen sich Programmierer zu nutze, und nutzen diesen Seiteneffekt aus, ohne das Ergebnis der Verknüpfung (true oder false) irgendwwo zu verwenden, weiterzugeben. Das wirkt beim ersten Lesen befremdlich und unvollständig, aber man lernt es leicht, vesteht es, und will es nicht mehr missen. Konkret wird hier also, je nach dem ob a kleiner als b ist oder nicht a von b abgezogen oder umgekehrt. Man nennt die Funktion dann beispielsweise absdiff, nicht e17, damit man leichter versteht, wozu sie gut ist.
Wenn Du eine Funktion oder ein Programm aufrufst, dann unterscheidet man die Parameter nach ihrer Position. ... Funktion oder Programm ist "echo", die Parameterzahl ist 4, der erste ist $1 (foo), der zweite $2 (bar), der dritte $3 ist hier 3 und der 4. ist "4 und Ende" $4.
Aha, ok, danke für die ausführliche Erklärung. Ich bin mir zwar jetzt noch nicht sicher wie ich das verwenden soll, aber das müsste ich mal praktisch testen...
Sowohl Dein Script kann die Parameter auswerten, die übergeben wurden (wenn welche übergeben wurden), als auch Funktionen innerhalb des Scripts, die nach dem gleichen Muster arbeiten.
Nein, nicht 3x die gl. Variable holen. Du hast 3 Codeblöcke gehabt, 2 davon mit einer 11, das ist die Zeilenzahl von Arduino2, die überschritten werden soll. Beim 3. Mal nur 3.
Aha, das müsste dann eben bevor ich am Arduino etwas geändert hatte gewesen sein, als es noch zusätzlich zu jedem Wert immer 0 für "ausgeführt" zurück meldete, und dann wären (vielleicht -gt?) 11 Zeilen für die 6 bisherigen Sensoren, und 3 Zeilen wäre dann nur 1x das überschreiben mit 0 (weil wusste es irgendwann mal nicht besser), und die 2 fache Rückmeldung für irgend etwas das nur 1 Durchgang war auf dem Arduino, irgend einen Sinn hatte das sicher, es bedeutete warten bis Arduino fertig ist.
Ja, das sind fachliche Arduinofragen, dazu kann ich mich nicht kompetent äußern.
Du kannst ja alle aus einer Sammlung herauskopieren am Anfang, aber dann lösch alle, die Du nicht brauchst, oder kommentiere sie aus.
ja, irgendwann hätte ich das vielleicht gemacht, hatte nur grad keine Lust dazu, wenn ich das überhaupt gemacht hatte, wahrscheinlich wollte ich dann eben nur mal schnell testen und ein neues Script schreiben, dass dann wie immer viel grösser und länger wurde als gedacht.
Ja, Dinge die man aufschiebt, macht man nie, d.h. entweder Du gewöhnst Dir das Aufschieben ab, oder Du kopierst nur das in das Skript, was Du sicher brauchst. Liegt das Script erst mal 2 Wochen rum wird es viel schwerer, zu löschen was Du nicht brauchst.
Beim Nachdenken über den Code muss man die alle im Kopf behalten - das schafft man nicht. Bei 5-7 Variablen ist normalerweise Schluss. Variablen, die man nicht sieht, über die kann man sich nicht unnötig Sorgen machen. Wenn eine Variable wiederverwendet wird, dann lohnt es sich auch, ihr einen guten Namen auszusuchen.
Ich brauche aber einfach viel mehr als 10, manchmal werden es über 100 verschiedene, und min 90% wird wahrscheinlich auch wirklich gebraucht.
Hast Du mal shellcheck installiert, und überprüft, was Dein Script braucht? Du lügst Dir in die eigene Tasche!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 | shellcheck orig-arduino.sh | grep "appears unused"
^-- SC2034: a3 appears unused. Verify it or export it.
^-- SC2034: a4 appears unused. Verify it or export it.
^-- SC2034: a9 appears unused. Verify it or export it.
^-- SC2034: d6 appears unused. Verify it or export it.
^-- SC2034: e6 appears unused. Verify it or export it.
^-- SC2034: f1 appears unused. Verify it or export it.
^-- SC2034: f2 appears unused. Verify it or export it.
^-- SC2034: f3 appears unused. Verify it or export it.
^-- SC2034: f4 appears unused. Verify it or export it.
^-- SC2034: f5 appears unused. Verify it or export it.
^-- SC2034: g1 appears unused. Verify it or export it.
^-- SC2034: g2 appears unused. Verify it or export it.
^-- SC2034: g3 appears unused. Verify it or export it.
^-- SC2034: g4 appears unused. Verify it or export it.
^-- SC2034: g5 appears unused. Verify it or export it.
^-- SC2034: f6 appears unused. Verify it or export it.
^-- SC2034: g6 appears unused. Verify it or export it.
|
Das sind 17 Variablen, die den Namensraum und das Hirn dessen vermüllen, der es analysieren will. Du müsstest 170 haben, wenn Deine 90% stimmen würden. Du hast vielleicht 34 (davon 20 bestimmt überflüssig, weil kein Array benutzt wurde).
Jetzt bei diesem Script waren es bisher erstaunlich wenig, fast keine, nur e2 - e6 die einfach aufgezählt werden und für irgend etwas gebraucht werden, normalerweise sind das eher 20 30, selten auch mal über 100. Deswegen denke ich kann ich das auch vergessen mit den guten Namen ausdenken.
Je mehr es sind, desto wichtiiger sind gute Namen. Ein seitenlanger Code mit 3 Variablen lässt sich ganz gut analysieren.
Und ich will es auch so machen mit so vielen Variablen, so komme ich mit Rechnen besser an den Punkt zu dem ich möchte, auch Dateien benenne ich manchmal nur noch mit Zahlen, damit ich gleich zum Namen komme durchs Rechnen.
Das eine schließt das andere nicht aus.
| grep port orig-arduino.sh
a2="/dev/ttyUSB0"; # arduino port (1)
a10="/dev/ttyUSB1"; # 2. arduino port
|
Wie kommt man rechnerisch von a2 zu port 1 und zu USB0, bzw. von 10 zu 2 bzw. USB1? Gar nicht! Semikolons, das nur am Rande, benötigt man nur, wenn man einen Zeilenumbruch weglässt, also mehrere Kommandos in einer Zeile hat, in der Shell. Das ist hier nicht C, C++ oder Java. Anführungsstriche nur, wenn man Leerzeichen usw. maskieren will.
grep port orig-arduino.sh
port0=/dev/ttyUSB0 # arduino ports
port1=/dev/ttyUSB1
}}} So sehen sinnvolle Variablennamen aus.
Ginge sicher auch anders, aber je nach dem ist es vielleicht sogar praktischer wenn es Zahlen sind, zB wenn es so etwas wie eine Karte werden soll, für irgend etwas ganz anderes. Am liebsten hätte ich ich bräuchte eigentlich nur noch Variablen und kann ein Script nur noch rechnerisch mit while und if und Variablen zusammen bauen, so dass ich immer durch die Rechnung gleich an dem Punkt bin wo ich sein will (wenn das jetzt noch verständlich ist)...
Du könntest Assemblerprogrammierer werden. Gelegentlich werden noch Cobolprogrammierer gesucht, weil die gerade aussterben, aber ihre Systeme noch laufen.
Ein aussagefähiger Name ist da viel besser. Wenn Du Angst hast, die Länge des Variablennamens hätte einen Einfluss, miss es nach.
Habe ich gar noch nicht dran gedacht...
Komm nicht auf dumme Gedanken! Compiler und Interpreter sind fast immer schnell genug. Sich da Geschwindigkeitsvorteile zu erhoffen ist lächerlich - siehe meine 0.5 MB, die in weniger 0.003 s gelesen werden.
Schleifen, die eine bestimmte Zahl an Durchläufen absolvieren, schreibt man mit einer for-loop, dafür wurde sie gemacht
Aha ok, gut zu wissen. Aber ich habe nie nachgeschaut wie eine for loop funktioniert, hatte das vor Jahren am Anfang mal angeschaut, und bin grad nicht draus gekommen und hatte auch nie einen Grund etwas anderes als eine while Schleife zu verwenden. Auch das while read line kannte ich bis zum Hauptscript nicht, ich musste noch nie jede Zeile einer Datei durchsuchen, nur bestimmte Zeilen, die ich mit sed -n Xp herausgesucht hatte.
Mit "draus gekommen" meinst Du "drauf gekommen"?
Nein, ich meinte wirklich ich hatte es nicht verstanden, das war noch ganz am Anfang als ich anfing Scripte zu schreiben, ich denke ich würde es heute schnell verstehen (müsst mich jetzt aber nicht grad testen (-: ), da ich while read line auch verstehe, aber ich hatte einfach noch nie das Verlangen danach etwas anderes als die alte übliche while Schleife zu benutzen, die hat gut funktioniert. Könnte ich mir anschauen mit der for loop.
Die Redewendung "drauskommen" kannte ich noch nicht, habe jetzt nachgeschaut, aber lt. Duden https://www.duden.de/rechtschreibung/drauskommen und auch Deiner Erklärung bedeutet sie doch, wie vermutet, das gleiche wie "draufkommen", in dem Zusammenhang, etwas verstehen. Nur ist es keine Marotte von Dir, wie ich vermutet habe, sondern verbreitet. ☺
Eine Zählvariable, die außerhalb der while-Schleife deklariert wird, wirkt, als müsse der Wert auch außerhalb und später bekannt sein, sprich, man muss sie beim Analysieren des Codes im Kopf behalten. Die Shell erlaubt leider keine Beschränkung der Sichtbarkeit von Variablen, aber man verschlimmert es, wenn man Variablen weit vor dem Gebrauch initialisiert.
Das habe ich auch meistens im Kopf, das ich die Variable vielleicht auch ausserhalb der Schleife wieder brauche, ob es dann wirklich auch so ist sehe ich dann erst später.
Das kommt so selten vor, dass man es später einbaut, wenn man es braucht. Nicht auf vagen Verdacht hin etwas einbauen, was man noch nicht braucht. Das YAGNI-Prinzip.
Ausser es ist jetzt wirklich nur eine reine Zählvariable, die nur genau für diese eine Schleife ist, ohne Verbindung zu irgend etwas anderem. Bei meinem Script sollte es aber glaube ich immer (oder meistens) eine Verbindung zu den d1 Variablen haben, die die Nummer von den Servos und Sensoren sind.
Das machst Du aber bei allen Schleifen, dass Du auf eine globale Variable zugreifst, die für nichts anderes da ist, als als Schleifenzähler zu dienen. Globale Variablen sind eines der größten Softwarerisiken! Vermeide sie, so oft es geht!
Das sed -n "Befehl(e)" DATEI kennst Du ja schon. "$zeile s/MUSTER/ERSETZUNG/gp" bedeutet, dass nach dem Muster MUSTER gesucht werden soll, und dieses durch ERSETZUNG (in unserem Fall: nix) ersetzt werden soll (s:substitute). Das Muster ist die Gruppe der Ziffern 0-9, aber sie ist mit dem führenden Caret ^ negiert. Und dann kommt noch ein g für "global", sonst wird nur das erste Muster ersetzt. Und dann kam wohl der Fehler, wieso nichts mehr geklappt hat: das $zeile p für print hinter dem g hatte ich vergessen. Sorry. Ich habe aber keine Testdaten.
Ah das geht auch mit durch nichts ersetzen... Diesen Befehl kenne ich auch, den habe ich in einer Notiz mit nützlichen Befehlen gespeichert, das ist immer mein "Zeile suchen und ersetzen" Befehl. Danke für die ausführliche Erklärung was das alles bedeutet bei diesem Befehl.
Ja, aber hast Du auch getestet, ob mit diesem Bugfix das von mir geänderte Programm - Du hattest ja bemängelt, dass nichts mehr geht - wieder läuft?
Statt f und g würde ich ja vielleicht f und s benutzen - Fotosensor und Sensor
ja wenns grad aufgeht mache ich das auch so, aber meistens geht es das nicht ganz und ich gehe einfach der Reihe nach, eben, sind meistens sehr viele Variablen, hier in diesem Script sind sie ja noch alle sehr kurz und übersichtlich.
Du versuchst Probleme zu heilen mit einer Kur, die sie verschlimmert. Eben der Dreh- und Angelpunkt 1 sind Arrays. Statt 6 gleichförmigen Variablen brauchst Du dann nur eine: | sensor=(01 02 03 04 05)
for sens in ${sensor[@]}; do echo 3$sens"0000" ; done
3010000
3020000
3030000
3040000
3050000
# ...
echo 3"${sensor[1]}"000 > $port2
|
Die Schreibweise mit geschweiften und eckigen Klammern ist zwar etwas umständlich, aber netto lohnt es sich.
Oder mit printf und offen für bis zu 100 Sensoren:
| for sens in ${sensor[@]}; do printf "3%02d0000\n" $sens; done
3010000
3020000
3030000
3040000
3050000
|
Das ${sensor[@]} ist das ganze Array und kommt auch mit Sparsearrays, also solchen, bei denen nur manche Indizees besetzt sind, zurecht: | declare -a hd
hd[5]=root
hd[6]=home
echo ${hd[@]}
root home
|
Sehe ich das richtig, dass Sensorwerte aufnehmen das gleiche ist, wie Initfotosensor, nur mit zeitlichem Abstand und daher anderen Werten? Wieso sind gleiche Werte ein Error - kann das nicht vorkommen?
Es ist für mich jetzt sehr schwierig all diesen neuen Befehlen hinterher zu kommen, mit dem das ich mir noch etwas unsicher mit dem $0 bin, dem dazugehörigen Text im Script, der for schleife, die ich auch noch nicht nachgeschaut habe, und auch über den sed Befehl, mit den $0 $1, ohne das der sed Befehl scheinbar eine Eingabedatei bekommt?
Ja, das $0 hätte ich erklären sollen. Die Parameter eines Scripts sind $1 $2 $3 usw. Wenn Du jetzt in der Befehlszeile rückwärts rechnest, was mag dann $0 sein?
Du hast es erraten – echo, der Befehl oder das Programm selbst, besser gesagt sein Name. Es ist nicht allgemein gute Praxis, die Daten, die man verarbeiten will, in das Programm selbst zu schreiben; es ist ja vollkommen unflexibel. Aber für das Testskript fand ich es praktisch, um nicht 2 Dateien angeben zu müssen, die Du brauchst, um den Code zu testen. Der miese Kommentartrick gibt die Testwerte ins Nirgendwo hin aus, erlaubt aber die Werte ins Skript selbst zu schreiben, ohne dass das negative Nebeneffekte für dieses hat. Das selbst=$0 sorgt dafür, dass das Script selbst (daher der Name) der Dateiname wird, aus der sed die Werte von liesZiffernAusZeile liest.
Ist das wirklich richtig, oder hast du da vielleicht auch mal die Eingabedatei vergessen? Egal, ich kann Dir jedenfalls ganz einfach sagen wieso Error wenn weitere Zahl: Der Arduino erwartet immer 6 Zahlen, plus ein 7. Zeichen, das entweder das End-Zeichen
Was ist denn das End-Zeichen? EOF? Vielleicht habe ich aber den Testcode unangepasst ins Skript übernommen. Die auskommentierte Sedzeile ist natürlich
falsch, richtig ist vielleicht die darunter, aber vielleicht muss es auch $speicher/speicher/speicher3 heißen: | liesZiffernAusZeile () {
zeile=$1
# sed -n "$zeile s/[^0-9]//g; $zeile p" $selbst
sed -n "$zeile s/[^0-9]//g; $zeile p" $speicher/speicher3
}
|
... Hoffe du verstehst was ich meine, der Arduino erwartet 6 Zahlen + 1 Zeichen, wenn die 7. Stelle wieder eine Zahl ist stimmt die Reihenfolge nicht mehr.
Tja, hast Du später gemerkt, dass es was anderes ist. Bei schlecht benannten Variablen blickt man nicht mehr durch.
Probier es aus: printf ...
Das habe ich schon, danke. Es funktioniert so wie im Code eine Antwort vor deiner letzten. Und ich meinte übrigens die Dauer solch eines printf Befehls mit 50 6er Zahlenblöcke, inklusive 3stelliger Variable, dauert nur 0.003s und nicht 0.03.
Und vor Dir haben es andere auch einfach so gemacht, und gemerkt, dass man damit auf die Nase fällt, immer wieder, wenn man es nicht ändert.
Also ich falle im Moment nicht auf die Nase, habe ich jedenfalls das Gefühl. Meinen Probleme in diesem Script liegen ganz wo anders,
Nein, man merkt doch, dass Du selbst Deine Variablen nicht erkennst. Du kannst sie auch nicht mal eben jemandem zeigen, der nicht das ganze Script kennt und analysiert und einem Refaktoring unterzieht, damit er eine Chance hat, zu verstehen, was passiert. Das ein Intervall von 5 bis 5 ein wenig klein ist, das versteht man, und wie ein Intevall mit min=x und max=y beschaffen ist, versteht man auch, aber nicht wenn min nicht min heißt, sondern d und max heißt f, weil das der nächste Buchstabe war, der frei war. Das ist einfach eine Zumutung - nicht nur für andere, auch für Dich.
dann am ehsten noch bei einem printf Befehl für 50 6er Zahlenblöcke mit Array und 3stelliger Variable darin,
Ja, zugegeben, Array und printf waren Wissenslücken. Sei dankbar, dass Du sie hattest, und hier viel schlimmere Probleme zu beheben lernst.
glücklicherweise ist alles durch : getrennt, sonnst wäre es sehr mühsam das zu durchblicken. Überhaupt habe ich eigentlich nur wirklich Probleme mit dieser (nicht mehr nötigen) Zeile aus dem alten Script: echo "1"$(eval 'echo $d'$(($(($e3-1))/2)) )""$(printf "%03d\n" "$(($(( 180000000/$(eval 'echo $h'$(( $(($e3-1)) /2)) ) * $(($e4 - $(eval 'echo $i'$(( $(($e3-1)) /2)) ) )) )) /1000000))")"" > $a2 # rechnen und winkel befehl senden
Das kann kein Mensch verstehen. Ein Berater, der 120€ Stundensatz hat, vielleicht. Leider sind wir Programmierer immer so ehrgeizig, solche Probleme lösen zu wollen, und ob wir jetzt das neueste Sudoku von Logic-Masters-Germany lösen oder so eine Zeile - es fordert einen heraus, wie Berg, den man besteigt, weil er da ist. Aber nicht vor Morgen.
Da habe ich absolut keine Überblick mehr darüber was gerechnet wird, ich sehe nur noch 2 Klammern auf, 1 zu, 1 auf 2 zu, paar andere Sonderzeichen...
Ach, plötzlich?
Die konnte ich nur grad knapp fertig stellen und wusste am Schluss nicht mehr was das ganze eigentlich schon wieder bedeutet, irgendwie hatte ich es auch mal schön kommentiert eine Zeile oberhalb, aber irgendwie sehe ich jetzt da auch nichts mehr schön kommentiert. Und ich mache es ja jetzt sowieso anders mit dem printf Befehl den ich schon als richtiges Beispiel aufgeschrieben habe. Und mir fällt auch auf das ich vielleicht nicht alles grad in einem Satz hätte rechnen müssen, und es dann auch übersichtlicher gewesen wäre.
Aha.
Also meine Probleme liegen ganz wo anders als Du sie im Moment siehst, das mit den Variablen Blöcke am Anfang und den nichts aussagenden Variablen Nummern macht mir kein Problem, kann ich so machen wenn ich will, hält mich nicht auf das Script zu schreiben, sehe auch nicht grad etwas das in allem besser ist und 10x schneller geht, wenn man eben bedenkt das ich sowieso auch Dateien manchmal nur noch mit Zahlen benenne (was sicher gar niemand eine gute Idee findet (-: ).
Weil Du nicht einpreist, dass es immer wieder zu Situationen kommt, in denen man Kontakt mit anderen hat, denen man das Skript zeigt. Etwa wenn Dich jemand fragt, wie man einem Arduino so etwas beibringt und Du hast so einen alphabeitsch strukturierten Müllhaufen als Beispiel anzubieten oder hast eine Frage und willst andere fragen, wieso das mit Minimum/Maximum nicht klappt, und im ganzen Code kommt kein Minimum vor.
Je nach Stift oder Pinsel gibt es auch ungünstige und günstige Stifthaltungen. Ein Rechtshänder mag einem Linkshänder keine guten Tipps geben können, aber ein etwas älterer Hase blickt eben geläutert auf die Fehler seiner Jugend zurück.
Ja das kann schon sein, Tipps sind sicher nicht schlecht. Aber vielleicht probiert man trotzdem lieber einfach mal frei drauf los, und nicht ganz genau nach Schema. Hauptsache ich bin glücklich beim scripten, nützt eine schöne Darstellung nichts wenn ich dauernd wieder (für mich gesehen) unnötigerweise Abstände lösche und einfüge kann für while done. Und wenn es zT. über 100 Variablen werden, und das immer noch gewünscht ist, ist das mit der Auflistung am Anfang auch nicht mehr so verkehrt, vielleicht.
Hast Du kein Syntaxhighlightening? Welchen Editor benutzt Du?
Ich weiss es nicht, ich benutze das was aufgeht wenn man auf einem normalen Ubuntu System editor im Terminal eingibt. Ich komme bei vielem nur minimal draus, ich mache einfach was ich machen kann, ohne mich immer über alle anderen möglichen Funktionen zu informieren, wenn sie nicht grad selbsterklärend sind.
Und wenn Du
| l $(which editor)
# eingibst, kommt
# .... /usr/bin/editor -> /etc/alternatives/editor
# dabei raus?
# was ergibt dann:
l /etc/alternatives/editor
|
Stimmen diese Kommentare eigentlich?
d1=01 # photosensor 1
Ja das stimmt schon, die d Variablen werden hier nur dazu benutzt um die zwingend 2 stellige Servo/Sensor Nummer zu beinhalten. Diese werde ich jetzt in ein Array einfügen. Nur der Kommentar dazu stimmt natürlich nicht, es ist nicht immer der Sensor 1, sonder 1, 2 ... Das wurde kopiert und vergessen zu ergänzen.
Tja, ist oben ja schon abgehandelt. Sind eigentlich alle Sensoren Photosensoren oder gibt es mehrere Sorten Sensoren?
Edit: Ah nein, bei der Frage wegen der Error Meldung, das war im bash Script gar nicht weil der Arduino immer 6 Zahlen und 1 Zeichen erwartet, ich war irgendwie bei dem, weil auf dem Arduino gibt es das eben auch, aber von dort kommt ein Error wenn 7. Zahl nicht grösser 9 oder kleiner 0 ist. Du meinst wahrscheinlich den Punkt an dem ein Error (der einzige den ich jetzt grad mit grep gefunden habe im bash Script) ausgegeben wird, wenn min_wert und max_wert genau gleich gross sind, dann funktioniert die Rechnung nicht mehr, und sowieso, das sollte nicht möglich sein, dann ist etwas falsch gelaufen bei dem physischen Ablauf der Servos und Fotosensoren. Und genau dort ist eben auch das Problem mit dem evtl. minus Ergebnis der Differenz von min_wert und max_wert, deshalb diese if's dort.
Tja, der min_wert, der max_wert, das würde man verstehen, wenn sie so hießen, aber sie heißen ja nicht so, damit ein wenig was zum Rätseln hat. Du hattest ja schon geschrieben, dass Du selbst nicht durchblickst, und immer einen zweiten Editor offen haben musst, mit dem Du oben im Script in Deiner Legende nachschaust, wie die heißen, als Krücke für Deine Benennungsstrategie, die Dich aber gar nicht behindert. Wenn Du stattdessen ein kl. Shellfenster öffnest, in dem Du grep suchen lässt, | grep -n "d1" orig-arduino.sh
14:d1=01 # photosensor 1
71:echo 3"$d1"000 > $a10
103:echo 3"$d1"000 > $a10
133:echo 3"$d1"000 > $a10
155:echo 3"$d1"000 > $a10
|
Ein grep -n sagt Dir, in welcher Zeile das Muster gefunden wurde. Mit Variablennamen wie f und g klappt das natürlich schlecht, weil jeder 2. Kommentar irgendwo ein f oder g enthält. Wie leich wäre es nach minSens oder max_sensor zu suchen! Kommentare in eh schon eingerückten Zeilen, die weit nach rechts rausragen, verschärfen das Problem und machen es unnötig schwer, diese Zeilen rauszufiltern. Wir verbleiben also für heute (von meiner Seite) bei dem kleinen Codeimprovement; statt:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 | # unterschied zwischen f und g ausrechnen
# i < e1 im Original
for ((i=1; i < sensorzahl; i+=1))
do
# wenn f < g, dann g-f und i=f, sonst umgekehrt
if (( f[i] < g[i] ))
then
# war h$i, i$i bzw. h$e1 oder e3, i$e1/e3
delta[$i]=$(( g[i] - f[i] ))
ii[$i]=${f[i]}
elif (( f[i] > g[i] ))
then
delta[$i]=$(( f[$i] - g[$i] ))
ii[$i]=${g[i]}
else
echo -e "\nERROR bei Nr. $i, f{[$i]}=${f[$i]} , g{[$i]}=${g[$i]}"
fi
# debug:
# echo ${delta[i]}":"${ii[i]}
done
|
was ein unübersichtlicher Block ist, dem man sich noch immer nicht recht nähern will, mit diesem netten Code: 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 | # Absolutwert der Differenz, also 30 und -30 => 30,
# bzw. abdiff (20, 50) == absdiff (50, 20) == 30
absdiff () {
a=$1
b=$2
(( a < b )) && echo $((b-a)) || echo $((a-b))
}
min () {
a=$1
b=$2
(( a < b )) && echo $a || echo $b
}
for (( i=1; i < sensorzahl; i+=1 ))
do
w1=${fotosensor[$i]}
w2=${sensor[$i]}
delta[$i]=$(absdiff $w1 $w2)
ii[$i]=$(min $w1 $w2)
if (( 0 == ${delta[$i]} ))
then
echo -e "\nERROR bei Nr. $i, fotosensor{[$i]}=$w1 , sensor{[$i]}=$w2"
fi
# debug:
# echo ${delta[i]}":"${ii[i]}
done
|
In den Funktionen absdiff und min ist die lästige und fehlerträchtige Arrayschreibweise weg. Sie sind auf Wiederverwendbarkeit angelegt und machen keinerlei Gebrauch von globalen Variablen. Isoliert sind sie leichter zu verstehen und leichter zu testen und der Name der Funktionen dokumentiert, was hier passiert. Die ganze For-loop bildet mit dem, was darin geschieht, eine semantische Einheit und sollte selbst in eine benannte Funktion ausgegliedert und einem beschreibenden Namen versehen werden, die dann vom Code ausgeführt wird. Vielleicht am Wochenende mehr ...
|
ka111
(Themenstarter)
Anmeldungsdatum: 22. Juni 2014
Beiträge: 141
|
user_unknown wc -l < /Pfad/Datei
Ja, mit Umleitung geht auch, gilt auch als eleganter, zeitlich nehmen die sich nichts - 0.003s bis 0.004s auch bei einer 0,5 MB Datei mit 3000 Zeilen.
Aha, ok, ja dann kommt es nicht (so) drauf an.
"if ist ja das gleiche, wie ."
Wieso existiert dann if überhaupt noch? Ist es im Hintergrund genau gleich schnell? Oder sogar etwas schneller ohne if? Sieht mir nach einer Wahl aus was man lieber hat, ohne grossen Vor oder Nachteile, abgesehen von der kürzeren Schreibweise. Das mit && und || verstehe ich dann schon, nur das man if auch einsparen kann wusste ich nicht. Meine Frage war aber eher ob es mit < > minus Zahlen als plus Zahlen interpretiert? Ich dachte das sollte so funktionieren, aber irgendwie hat es das nicht so richtig bei mir. Also (jetzt mit if) "if [ -51 > 50 ]" = true, wegen dem > anstatt -gt. Oder was ist der Unterschied zwischen <> und -lt -gt?
Hast Du mal shellcheck installiert, und überprüft, was Dein Script braucht? Du lügst Dir in die eigene Tasche!
Ich kenne shellcheck nicht, aber das kann nicht sein das alle d, f und g Variablen nicht gebraucht werden, vielleicht erkennt shellcheck nicht das bei solchen Zeilen: eval 'h'$e3=$(( $(eval 'echo $g'$e3) - $(eval 'echo $f'$e3) )) die f und g Variablen mit variablem Namen benutzt werden. Ausser ich habe e1 auf weniger als 6 gesetzt, dann werden nur so viele gebraucht wie e1 ist, weil das ist die maximale Anzahl möglicher Servos und Sensoren die im Moment genutzt werden. Die a Variablen werden schon zT nicht genutzt, die kommen eben auch aus anderen Scripten, die ich einfach bei allen wieder einfügen will, fals ich irgendwo mal etwas heraus kopiere und wieder ein. Besser wäre es das würde alles in einer Konfigurationsdatei stehen, dann müsste ich nur in dieser Datei etwas ändern und es gilt für alle Scripte.
Wie kommt man rechnerisch von a2 zu port 1 und zu USB0, bzw. von 10 zu 2 bzw. USB1? Gar nicht! (a2="/dev/ttyUSB0"; # arduino port (1) | a10="/dev/ttyUSB1"; # 2. arduino port)
Das sind jetzt auch nur die Pfade, da macht es auch meistens keinen Sinn mit denen etwas zu rechnen, a1 - ca 15 sind eher Ausnahmen, die man jetzt nicht als Beispiel benutzen sollte. Aber wenn alles nur noch mit Zahlen benennt wird, denke ich liegt es auf der Hand dass man zum einten oder anderen auch besser hin kommt mit Rechnen, was vielleicht nicht möglich wäre, oder mit Zusatzschritten erreicht würde. ZB. wenn der Name eines Scriptes 1 heisst, kann ich es gleich starten, wenn ich nach einer Rechnung auf 1 gekommen bin. Semikolons, das nur am Rande, benötigt man nur, wenn man einen Zeilenumbruch weglässt...
Ja ich benutze "" manchmal einfach zusätzlich, weil ich nicht genau weiss ob es jetzt unbedingt gebraucht wird oder einfach um es schön einzugrenzen, manchmal einfach wie ich grad Lust habe...
Du könntest Assemblerprogrammierer werden
Assembler war tatsächlich die einzige Sprache die mir vielleicht noch zugesagt hätte, als ich mal früher einem guten Tutorial gefolgt bin. Aber wozu brauche ich das jetzt schon wirklich? Ich werd ja wohl nicht den Terminal aufmachen und mit Assembler etwas anfangen wollen. Ich hielt es mir im Hinterkopf für Pixel Farben so schnell wie möglich auslesen, keine Ahnung ob man das mit Assembler machen könnte, ich hatte früher immer das Problem das ich Pixelfarben nicht genug schnell auslesen konnte, und ausweichen musste auf andere Sprachen, die auch nicht genug schnell waren so wie ich das machen wollte. Dann fing ich an zu sparen, und nicht immer alle Pixelfarben auslesen zu wollen, aber das ist wieder ein ganz anderes Thema, das ich im Moment nicht brauche.
Die Redewendung "drauskommen" kannte ich noch nicht, habe jetzt nachgeschaut, aber lt. Duden https://www.duden.de/rechtschreibung/drauskommen und auch Deiner Erklärung bedeutet sie doch, wie vermutet, das gleiche wie "draufkommen", in dem Zusammenhang, etwas verstehen. Nur ist es keine Marotte von Dir, wie ich vermutet habe, sondern verbreitet. ☺
Ich bin mir auch nicht ganz sicher bei dem Wort ob es nicht ein abgekürztes Dialekt Wort von mir ist, aber scheinbar nicht (-:
Das sed -n "Befehl(e)" DATEI kennst Du ja schon. "$zeile s/MUSTER/ERSETZUNG/gp" bedeutet, dass nach dem Muster MUSTER gesucht werden soll, und dieses durch ERSETZUNG (in unserem Fall: nix) ersetzt werden soll (s:substitute). Das Muster ist die Gruppe der Ziffern 0-9, aber sie ist mit dem führenden Caret ^ negiert. Und dann kommt noch ein g für "global", sonst wird nur das erste Muster ersetzt. Und dann kam wohl der Fehler, wieso nichts mehr geklappt hat: das $zeile p für print hinter dem g hatte ich vergessen. Sorry. Ich habe aber keine Testdaten.
Ah das geht auch mit durch nichts ersetzen... Diesen Befehl kenne ich auch, den habe ich in einer Notiz mit nützlichen Befehlen gespeichert, das ist immer mein "Zeile suchen und ersetzen" Befehl. Danke für die ausführliche Erklärung was das alles bedeutet bei diesem Befehl.
Ja, aber hast Du auch getestet, ob mit diesem Bugfix das von mir geänderte Programm - Du hattest ja bemängelt, dass nichts mehr geht - wieder läuft?
Nein, ich brauche es ja nicht unbedingt, sed -i geht auch. Oder was meinst du mit dem /gp am Schluss? Wir die gesuchte und gestrichene Zeile dann trotzdem noch ausgegeben? Das würde auch nicht funktionieren, dann würde es 50 nach einer Zeile neu suchen und ausgeben, was zu lange dauert, es muss alles in einem mal an ttyUSB0 gesendet werden, 50 echos mit 6 Zahlen gehen viel länger als 1 echo mit 300 Zahlen, weis nicht ob das an echo oder ttyUSB0 liegt, 50x echo aufrufen ist glaube ich auch nicht so effizient, wie du auch mal irgendwo gesagt hast. Und "for sens in ${sensor[@]}; do printf "3%02d0000\n" $sens; done" geht dann eben auch nicht, alles muss an einem Stück sein, nicht 50x neu durchlaufen werden. Vielleicht hat das auch mit ttyUSB0 zu tun, evtl braucht es Zeit um die übertragung anzufangen mit ttyUSB0, bin nich ganz sicher, hatte etwas gelesen und selbst getestet...
Ja, das $0 hätte ich erklären sollen. Die Parameter eines Scripts sind $1 $2 $3 usw. Wenn Du jetzt in der Befehlszeile rückwärts rechnest, was mag dann $0 sein?
Aha, $0 ist der Befehl selbst, ich dachte das 1. nach dem Befehl... Aber egal, es funktioniert ja auch ohne $0, $1 ... Ich habe jetzt schon wieder so viele neue Befehle gesehen, obwohl ich eigentlich nur den printf Befehl jetzt verwenden sollte um das Script mal fertig zu schreiben, und überhaupt nur mal zu sehen ob den das ganze überhaupt so funktioniert wie ich mir das vorstelle, oder ob ich dann sehe, nein funktioniert auch nicht, und dann vielleicht in einem Monat wieder ein Script schreibe, oder vielleicht auch nicht und erst wieder in einem Jahr... Bis dahin habe ich das wieder vergessen, und eigentlich wollte ich eher alle Befehle auf die ich verzichten kann raus schmeissen.
Was ist denn das End-Zeichen? EOF?
Vielleicht ein Line Feed, ich weiss es nicht genau, das was ttyUSB0 als 7. Zeichen bekommt wenn ich "echo 123456 > /dev/ttyUSB0" sende.
Aber nicht vor Morgen.
Bitte nicht noch mehr Erklärungen, ich bin Dir dankbar für die bissherigen, aber ich muss jetzt mal das Script schreiben, ich komme nie dazu...
Weil Du nicht einpreist, dass es immer wieder zu Situationen kommt, in denen man Kontakt mit anderen hat, denen man das Skript zeigt.
Das hat vielleicht etwas wahres dran...
Und wenn Du
l $(which editor)
/usr/bin/editor@
l /etc/alternatives/editor
/etc/alternatives/editor@
Sind eigentlich alle Sensoren Photosensoren oder gibt es mehrere Sorten Sensoren?
Ja, alle sind Photoresistor, also Widerstände die sich durch Licht verändern in ihrem Widerstand.
Vielleicht am Wochenende mehr ...
Es reicht vollkommen, danke. Ich muss jetzt selbst mal das Script schreiben. Edit: Keine Ahnung woher die 2 Punkte ganz zu unterst kommen, ich sehe nichts woher die kommen, bei mir steht nichts zu unterst.
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17548
Wohnort: Berlin
|
Die Bash hat 3 Sorten ifs, wenn man nur die ifs zählt, die auch if heißen. Das ist ein großer Mist, der sicher eine Historie hat, die es erklärt, aber mir wäre es lieber es gäbe nur eins. Die verlangen eine unterschiedliche Syntax und haben unterschiedliche Stärken und Schwächen. | if [ BEDINGUNG ]
if [[ BEDINGUNG ]]
if (( BEDINGUNG ))
|
alle gehen mit "then ... fi" weiter. Aber das ist ziemlich krank. Die doppelten, runden Klammern sind für arithmetische Ausdrücke geeignet, die anderen nicht. In einem der anderen (mindestens) kann man mit -lt, -le, -ne usw. arbeiten, aber inhaltlich ist -lt das gleiche wie < , da gibt es keines, welches den Betrag vergleicht. Das einzige, was Dir passieren kann, ist ein alphabetischer Vergleich, mit "7 kleiner 63", aber ich glaube nicht.
Wieso existiert dann if überhaupt noch? Ist es im Hintergrund genau gleich schnell? Oder sogar etwas schneller ohne if? Sieht mir nach einer Wahl aus was man lieber hat, ohne grossen Vor oder Nachteile, abgesehen von der kürzeren Schreibweise.
Ich denke, weil if älter ist als (( bedingung )) && a || b und letzteres auch bei Codeblöcken nicht gut aussieht.
Ich kenne shellcheck nicht, aber das kann nicht sein das alle d, f und g Variablen nicht gebraucht werden, vielleicht erkennt shellcheck nicht das bei solchen Zeilen:
Siehst Du, Dein Code wird selbst von Codecheckern nicht verstanden. ☺
e. ZB. wenn der Name eines Scriptes 1 heisst, kann ich es gleich starten, wenn ich nach einer Rechnung auf 1 gekommen bin.
Kein Argument: | scripte=(starten.sh rechnen.sh runterfahren.sh)
for script in ${scripte[@]}
do
./$script
done
cat ${scripte[1]}
|
Machst Du auch hier gar nicht. Wieder ein Fall für YAGNI.
Nein, ich brauche es ja nicht unbedingt, sed -i geht auch. Oder was meinst du mit dem /gp am Schluss? Wir die gesuchte und gestrichene Zeile dann trotzdem noch ausgegeben? Das würde auch nicht funktionieren, dann würde es 50 nach einer Zeile neu suchen und ausgeben, was zu lange dauert, es muss alles in einem mal an ttyUSB0 gesendet werden, 50 echos mit 6 Zahlen gehen viel länger als 1 echo mit 300 Zahlen, weis nicht ob das an echo oder ttyUSB0 liegt, 50x echo aufrufen ist glaube ich auch nicht so effizient, wie du auch mal irgendwo gesagt hast.
Ja, leider zitierst Du den Code nicht - keine Ahnung von welchem Codeschnipsel Du gerade sprichst.
Sowas hier: | g1=$(sed -n 3p $a8/speicher3 | tr -dc '0-9') # alle min sensor werte aufnehmen in g variablen, tr weil noch unsichtbare zeichen da sind
g2=$(sed -n 5p $a8/speicher3 | tr -dc '0-9')
g3=$(sed -n 7p $a8/speicher3 | tr -dc '0-9')
g4=$(sed -n 9p $a8/speicher3 | tr -dc '0-9')
g5=$(sed -n 11p $a8/speicher3 | tr -dc '0-9')
|
Das sind 5 Sedaufrufe. Der erste davon ist äquivalent zu sed -n "3 s/[^0-9]//gp" $a8/speicher3 usw.
-n heißt "nichts per default ausgeben (also nicht Zeile 1, 2, 4, ...). In Zeile 3 substituieren, alles was keine Ziffer ist durch nichts ersetzten. Das klein g sagt global, also nicht nur das erste Match ersetzen, das kl. p sagt print am Ende das Ergebnis (-n hatte ja gesagt "nicht printen").
Und "for sens in ${sensor[@]}; do printf "3%02d0000\n" $sens; done" geht dann eben auch nicht, alles muss an einem Stück sein, nicht 50x neu durchlaufen werden.
In dem Code, von dem ich das habe, waren es m.E. auch x Befehle und nicht ein großer. Abgesehen davon kannst Du auch Befehle/Strings zusammensetzen, probier es aus:
| s="" ; for i in {1..3}; do s="$s"$(printf "foo-%03d-bar\t" $i ); done ; echo -e "$s"
|
Aha, $0 ist der Befehl selbst, ich dachte das 1. nach dem Befehl.
Das erste ist $1 .
| l $(which editor)
/usr/bin/editor@
l /etc/alternatives/editor
/etc/alternatives/editor@
|
Ah, mein Fehler, ich habe einen anderen als den Standardalias für l gesetzt.
| ls -l $(which editor)
ls -l /etc/alternatives/editor
|
dann bitte.
Edit: Keine Ahnung woher die 2 Punkte ganz zu unterst kommen, ich sehe nichts woher die kommen, bei mir steht nichts zu unterst.
Zeile 4, wo jetzt so Arrayklammern stehen. Wenn Code nicht als solcher formatiert ist, passiert das leicht.
Codeblocks verwenden, und Backticks für Code im Fließtext.
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11176
Wohnort: München
|
user_unknown schrieb: Die Bash hat 3 Sorten ifs, wenn man nur die ifs zählt, die auch if heißen.
Das if ist bei deinen Beispielen im immer das selbe, das reagiert lediglich auf den Exit-Code des ausgeführten Statements (vgl. https://www.gnu.org/software/bash/manual/html_node/Conditional-Constructs.html). Was es gibt sind viele Varianten Tests zu implementieren bzw. die Möglichkeit beliebige Befehle auszuführen und ihren Exit-Code zu verarbeiten. Die Test-Konstrukte in einfachen eckigen Klammern sind die klassischen Tests, die doppelten eckigen Klammern sind compound Statements und die doppelten runden Klammern sind arithmetische Tests. Ob && und || Dinge schwerer lesbar machen hängt IMHO von den Gewohnheiten des Lesers ab. Ich finde
umständlicher als
if..else Statements verhalten sich auch anders als die mit && und || verknüpften Statements - letztere können hilfreich sein, wenn man einen Fehlerfall im Branch für den Wahrheitsfall abfangen will - ein Beispiel wäre z.B.:
| true && {
echo "Bedingung erfüllt"
false
} || echo "ein Fehler ist aufgetreten"
|
Das wird mit if..else dann verschachtelter:
1
2
3
4
5
6
7
8
9
10
11
12
13 | if true
then
if false
error=1
fi
else
error=1
fi
if (( error == 1 ))
then
echo "ein Fehler ist aufgetreten"
fi
|
|
ka111
(Themenstarter)
Anmeldungsdatum: 22. Juni 2014
Beiträge: 141
|
user_unknown Die Bash hat 3 Sorten ifs, wenn man nur die ifs zählt, die auch if heißen.
Das ist ein großer Mist, der sicher eine Historie hat, die es erklärt, aber mir wäre es lieber es gäbe nur eins.
... Die doppelten, runden Klammern sind für arithmetische Ausdrücke geeignet, die anderen nicht. In einem der anderen (mindestens) kann man mit -lt, -le, -ne usw. arbeiten, aber inhaltlich ist -lt das gleiche wie <, da gibt es keines, welches den Betrag vergleicht.
Aha, ok, dann kann ich ja einfach wieder eines auswählen, wenn < > das gleiche wie -lt -gt ist.
Wieso existiert dann if überhaupt noch? Ist es im Hintergrund genau gleich schnell? Oder sogar etwas schneller ohne if? Sieht mir nach einer Wahl aus was man lieber hat, ohne grossen Vor oder Nachteile, abgesehen von der kürzeren Schreibweise.
Ich denke, weil if älter ist als (( bedingung )) && a || b und letzteres auch bei Codeblöcken nicht gut aussieht.
Aha, ok..
Nein, ich brauche es ja nicht unbedingt, sed -i geht auch. Oder was meinst du mit dem /gp am Schluss? Wir die gesuchte und gestrichene Zeile dann trotzdem noch ausgegeben? Das würde auch nicht funktionieren, dann würde es 50 nach einer Zeile neu suchen und ausgeben, was zu lange dauert, es muss alles in einem mal an ttyUSB0 gesendet werden, 50 echos mit 6 Zahlen gehen viel länger als 1 echo mit 300 Zahlen, weis nicht ob das an echo oder ttyUSB0 liegt, 50x echo aufrufen ist glaube ich auch nicht so effizient, wie du auch mal irgendwo gesagt hast.
Ja, leider zitierst Du den Code nicht - keine Ahnung von welchem Codeschnipsel Du gerade sprichst. Sowas hier:
g1=$(sed -n 3p $a8/speicher3 | tr -dc '0-9') # alle min sensor werte aufnehmen in g variablen, tr weil noch unsichtbare zeichen da sind
g2=$(sed -n 5p $a8/speicher3 | tr -dc '0-9')
g3=$(sed -n 7p $a8/speicher3 | tr -dc '0-9')
g4=$(sed -n 9p $a8/speicher3 | tr -dc '0-9')
g5=$(sed -n 11p $a8/speicher3 | tr -dc '0-9') Ja, sowas wäre dann eine unnötige 5 fache Aufrufung von sed, anstatt zB 1x mit while read line darüber zu gehen, oder auch mit sed selbst. Und ich hatte irgendwie einen Satz von Dir überlesen, du hattest es sogar erklärt was gp am Schluss von sed bedeutet, global und print. Irgendwie kann ich sed aber gar nicht dazu verwenden Zeilen aus der Eingabedatei von ttyUSB0 zu löschen, es verhält sich als ob die Datei gelöscht wird und neu erstellt, dann kommt nichts mehr von tty in die Datei wenn ich nicht neu mit cat etwas hinein leite. Sed kopiert sicher alles andere was nicht gelöscht werden soll in eine temporäre Datei und löscht die alte, und erstellt sie wieder neu. Oder keine Ahnung warum sonst genau nach sed -i nichts mehr in der Datei von tty ankommt. Egal, überschreibe ich halt doch immer gleich die 50 erhaltenen Zeilen, nachdem ich sie benutzt habe, und frage nicht schon vorher nach den nächsten 50. Ausserdem habe ich noch etwas nützliches gefunden beim durchschauen meiner Sammlung aller nützlichen Befehle: ">/pfad/datei" überschreibt die Datei mit asbolut gar nichts, kein verstecktes Zeichen, und sogar schneller als mit echo.
Das sind 5 Sedaufrufe. Der erste davon ist äquivalent zu sed -n "3 s/[^0-9]//gp" $a8/speicher3 usw. -n heißt "nichts per default ausgeben (also nicht Zeile 1, 2, 4, ...). In Zeile 3 substituieren, alles was keine Ziffer ist durch nichts ersetzten. Das klein g sagt global, also nicht nur das erste Match ersetzen, das kl. p sagt print am Ende das Ergebnis (-n hatte ja gesagt "nicht printen").
Ah ja, hier erklärst du es ja nochmals, das hatte ich irgendwie überlesen...
Und "for sens in ${sensor[@]}; do printf "3%02d0000\n" $sens; done" geht dann eben auch nicht, alles muss an einem Stück sein, nicht 50x neu durchlaufen werden.
In dem Code, von dem ich das habe, waren es m.E. auch x Befehle und nicht ein großer.
Ich weiss jetzt grad nicht von wo du meinst, von mir, und du meinst ich habe es aber auch so gemacht, oder sonst? Auch egal, ich brauche jedenfalls "printf "1${a[1]}%03d:1${a[2]}%03d:1${a[3]}%03d" $b1 $b2 $b3 > /dev/ttyUSB0". Und das:
Abgesehen davon kannst Du auch Befehle/Strings zusammensetzen, probier es aus:
s="" ; for i in {1..3}; do s="$s"$(printf "foo-%03d-bar\t" $i ); done ; echo -e "$s" geht glaube ich nicht, weil es wird mehrmals s=$(print) gemacht, was eben komischerweise viel länger geht als s=1 oder einfach nur print ..., wie eben auch echo $(echo ...) viel länger geht als einfach nur echo. Und hier:
ls -l $(which editor)
lrwxrwxrwx 1 root root 24 Mai 20 2018 /usr/bin/editor -> /etc/alternatives/editor
lrwxrwxrwx 1 root root 9 Mai 20 2018 /etc/alternatives/editor -> /bin/nano
seahawk1986 Ob && und || Dinge schwerer lesbar machen hängt IMHO von den Gewohnheiten des Lesers ab.
Ich finde
...
umständlicher als
...
Ja das stimmt schon, es würde etwas übersichtlicher aussehen, wie gekürzter Code, vorallem das verschachtelte if else sieht unübersichtlicher aus, so sieht es eben bei mir immer aus. Aber ich müsste mir das zuerst angewöhnen, eigentlich weiss ich nicht einmal was if foo sein soll, foo sollte dann nur true oder false beinhalten, was ja noch Sinn machen würde, im Gegensatz zu true &&, wie geht den das? Aber egal, ich mache mal das Script weiter...
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17548
Wohnort: Berlin
|
ka111 schrieb: user_unknown
Aha, ok, dann kann ich ja einfach wieder eines auswählen, wenn < > das gleiche wie -lt -gt ist.
Ja, leider nicht frei aussuchen, weil je nach Klammerntyp kann man entweder das eine oder das andere benutzen, bzw. man muss. Du kannst aber umgekehrt den Klammerntyp abhängig vom Vergleichsoperator wählen.
Ja, leider zitierst Du den Code nicht - keine Ahnung von welchem Codeschnipsel Du gerade sprichst. Sowas hier:
g1=$(sed -n 3p $a8/speicher3 | tr -dc '0-9') # alle min sensor werte aufnehmen in g variablen, tr weil noch unsichtbare zeichen da sind
g2=$(sed -n 5p $a8/speicher3 | tr -dc '0-9')
g3=$(sed -n 7p $a8/speicher3 | tr -dc '0-9')
g4=$(sed -n 9p $a8/speicher3 | tr -dc '0-9')
g5=$(sed -n 11p $a8/speicher3 | tr -dc '0-9') Ja, sowas wäre dann eine unnötige 5 fache Aufrufung von sed, anstatt zB 1x mit while read line darüber zu gehen, oder auch mit sed selbst.
Bei einer Schleife wird auch 5x sed aufgerufen, es steht nur nicht 5x der Sedbefehl da. Dito bei while/read.
Irgendwie kann ich sed aber gar nicht dazu verwenden Zeilen aus der Eingabedatei von ttyUSB0 zu löschen, es verhält sich als ob die Datei gelöscht wird und neu erstellt, dann kommt nichts mehr von tty in die Datei wenn ich nicht neu mit cat etwas hinein leite.
Ja. Sowas wie /dev/ttyUSB0 ist eine Pseudodatei. Genau kann ich es nicht beschreiben, aber wenn Du es einmal liest ist es weg. Du kannst wohl einzelne Zeilen daraus lesen, und die späteren Zeilen sind dann noch da, wenn Du zeilenweise liest und verarbeitest. Ist die Reihenfolge der Daten vorher bekannt geht das auch. Ansonsten musst die Daten an eine Stelle kopieren, wo sie liegenbleiben, bis Du sie löschst oder überschreibst. Oder Du kopierst sie in einen String im Speicher, und arbeitest dann mit diesem. Am besten probierst Du das in einem separaten Testscript, bis klappt.
Sed kopiert sicher alles andere was nicht gelöscht werden soll in eine temporäre Datei und löscht die alte, und erstellt sie wieder neu. Oder keine Ahnung warum sonst genau nach sed -i nichts mehr in der Datei von tty ankommt.
Sed -i eignet sich nicht für das Lesen von einer /dev-Datei, über die ein Datenstrom reinkommt. Allerdings fand ich in Deinem Script nur eine Verwendung von port1 (USB0), schreibend und etwa ein Dutzend für port2 (USB1), aber auch alle schreibend.
Egal, überschreibe ich halt doch immer gleich die 50 erhaltenen Zeilen, nachdem ich sie benutzt habe, und frage nicht schon vorher nach den nächsten 50. Ausserdem habe ich noch etwas nützliches gefunden beim durchschauen meiner Sammlung aller nützlichen Befehle: ">/pfad/datei" überschreibt die Datei mit asbolut gar nichts, kein verstecktes Zeichen, und sogar schneller als mit echo.
Und "for sens in ${sensor[@]}; do printf "3%02d0000\n" $sens; done" geht dann eben auch nicht, alles muss an einem Stück sein, nicht 50x neu durchlaufen werden.
In dem Code, von dem ich das habe, waren es m.E. auch x Befehle und nicht ein großer.
Ich weiss jetzt grad nicht von wo du meinst, von mir, und du meinst ich habe es aber auch so gemacht, oder sonst? Auch egal, ich brauche jedenfalls "printf "1${a[1]}%03d:1${a[2]}%03d:1${a[3]}%03d" $b1 $b2 $b3 > /dev/ttyUSB0". Und das:
Solche Zeilen müssen in einen Codeblock, oder zwischen Backticks:
Siehe: "printf "1${a[1]}%03d:1${a[2]}%03d:1${a[3]}%03d" $b1 $b2 $b3 > /dev/ttyUSB0"
Abgesehen davon kannst Du auch Befehle/Strings zusammensetzen, probier es aus:
s="" ; for i in {1..3}; do s="$s"$(printf "foo-%03d-bar\t" $i ); done ; echo -e "$s" geht glaube ich nicht, weil es wird mehrmals s=$(print) gemacht, was eben komischerweise viel länger geht als s=1 oder einfach nur print ..., wie eben auch echo $(echo ...) viel länger geht als einfach nur echo.
Das verstehe ich nicht (Satzbau, Grammatik). Es wird nicht einfach s=$(print ...) gemacht, sondern s=$s$(print ...) - vielleicht hast Du das schon mal bei der Pfadvariablen gesehen: PATH=/home/ka111/bin:$PATH - die Variable wird um einen eigenen String verlängert; sie wird hinten noch mal zugefügt aber dem gleichen Namen wieder zugewiesen. Äquivalent wäre: 1
2
3
4
5
6
7
8
9
10
11
12 | neupfad=/home/ka111/bin:$PATH
PATH=$neupfad
# oder
s="foo bar"
t=baz
u=$t$s
s=$u
# ist äquivalent zu:
s="foo bar"
t=baz
s=$t$s
|
In einer Schleife wird das s länger und länger.
Und hier:
lrwxrwxrwx 1 root root 9 Mai 20 2018 /etc/alternatives/editor -> /bin/nano
Aha, nano ist Dein Defaulteditor. Du kannst ja mal Geany ausprobieren, der ist recht schlank aber nicht ganz so spartanisch wie nano. Immerhin hat nano Syntaxhighlightening, d.h. v.a., es gibt keinen guten Grund mehrere Leerzeilen zur Codestrukturierung zu benutzen. Noch was zu sed -n und sed -i : In Kombination wird ein erstes Kommando alle Zeilen bis auf eine löschen, wenn nur 1 Zeile aufs Muster passt - eine zweite Suche wird den Rest löschen, wenn das Muster fooo001 und fooo002 ist, und pro Zeile nur ein eindeutiges foo000x vorkommt. Und hier noch ein kleines Testscript, für echo mit while auf 3 Arten:
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
52
53
54
55
56
57
58
59
60
61
62
63 | #!/bin/bash
#
sensor1=01
sensor2=02
sensor3=03
sensor4=04
sensor5=05
# alternative mit Array
sensor=(01 02 03 04 05)
# stdout statt USBx, zum Testen
port2=/dev/stdout
# echo -n verhindert einen Zeilenumbruch am Ende - suchst Du nicht sowas?
komSpeicherLeeren () {
echo "0" > /tmp/muell
echo -n 3"$sensor1"000 > $port2
echo -n 3"$sensor2"000 > $port2
echo -n 3"$sensor3"000 > $port2
echo -n 3"$sensor4"000 > $port2
echo -n 3"$sensor5"000 > $port2
echo > $port2
}
# Hier mit Array:
ksl2 () {
echo "0" > /tmp/muell
for i in {1..5}
do
echo -n 3${sensor[i]}000
done > $port2
}
# Beachte, dass die Umlenkung nach $port2 erst ganz am Ende, außerhalb für die ganze Schleife aufgerufen wird.
# Scheint meiner Beobachtung nach schneller zu sein.
# kryptische {x..y} (von - bis) Schreibweise.
ksl3 () {
echo "0" > /tmp/muell
echo -n 3{01..05}000 > $port2
}
# Scheint mir am schnellsten, aber {x..y} lässt sich nicht in immer in den Code integrieren. Man kann beispielsweise
# da keine Variablen benutzen wie {1..$maxsensors}
# Um zuverlässigere Ergebnissse zu bekommen, die Dauer von 100 Aufrufen messen
miss () {
cmd=$1
for i in {1..100}; do $cmd ; done
}
# time miss komSpeicherLeeren
# time miss ksl2
# time miss ksl3
# Die Umleitung nach /dev/null macht das Ergebnis übersichtlicher, aber vielleicht
# optimiert man da gerade den kritischen Teil der Messung weg. Also auch mal ohne Umleitung messen!
time miss komSpeicherLeeren >/dev/null
echo
time miss ksl2 >/dev/null
echo
time miss ksl3 >/dev/null
|
|
ka111
(Themenstarter)
Anmeldungsdatum: 22. Juni 2014
Beiträge: 141
|
user_unknown Bei einer Schleife wird auch 5x sed aufgerufen, es steht nur nicht 5x der Sedbefehl da. Dito bei while/read.
Ja, deshalb besser: | declare -A a
var1=1
while read -r line; do
a[$var1]="${line//[^0-9]/}"
var1=$(($var1+1))
done < /pfad
|
Oder das gleiche mit einem anderen Befehl der das kann, vielleicht sed selbst. Das '"${line//[^0-9]/}"' hatte ich übrigens auch noch heraus gefunden... Weiss zwar nicht wieso es immer noch 4 Zeichen sind wenn die Zahl 3stellig ist, aber nachher lässt sich damit rechnen...
Ja. Sowas wie /dev/ttyUSB0 ist eine Pseudodatei. Genau kann ich es nicht beschreiben, aber wenn Du es einmal liest ist es weg. Du kannst wohl einzelne Zeilen daraus lesen, und die späteren Zeilen sind dann noch da, wenn Du zeilenweise liest und verarbeitest. Ist die Reihenfolge der Daten vorher bekannt geht das auch.
Ansonsten musst die Daten an eine Stelle kopieren, wo sie liegenbleiben, bis Du sie löschst oder überschreibst. Oder Du kopierst sie in einen String im Speicher, und arbeitest dann mit diesem.
Am besten probierst Du das in einem separaten Testscript, bis klappt.
Das mache ich eigentlich auch, dazu werden 2 andere Scripte gestartet die die beiden Arduinos konfigurieren und mit '"cat /dev/ttyUSB0 > Eingabedatei &"' das in die Eingabedatei lenken. Aber wenn sie gelöscht wird von sed funktioniert es nachher nicht mehr. Jedenfalls bekomme ich einfach nichts mehr wenn ich mit sed Zeilen heraus lösche, aber überschreiben mit echo oder direkt nur > geht.
Sed -i eignet sich nicht für das Lesen von einer /dev-Datei, über die ein Datenstrom reinkommt. Allerdings fand ich in Deinem Script nur eine Verwendung von port1 (USB0), schreibend und etwa ein Dutzend für port2 (USB1), aber auch alle schreibend.
Ja, Arduino 1 wird vor diesem Script schon gestartet, und das Script für Arduino 2 wird von diesem Script gestartet am Anfang. Danach beinhaltet speicher3 alles vom 2. Arduino tty. Aber Befehle an die 2 muss ich halt immer noch über den Port senden.
geht glaube ich nicht, weil es wird mehrmals s=$(print) gemacht, was eben komischerweise viel länger geht als s=1 oder einfach nur print ..., wie eben auch echo $(echo ...) viel länger geht als einfach nur echo.
Das verstehe ich nicht (Satzbau, Grammatik).
Es wird nicht einfach s=$(print ...) gemacht, sondern s=$s$(print ...) - vielleicht hast Du das schon mal bei der Pfadvariablen gesehen: PATH=/home/ka111/bin:$PATH - die Variable wird um einen eigenen String verlängert; sie wird hinten noch mal zugefügt aber dem gleichen Namen wieder zugewiesen.
Ja das habe ich schon verstanden dass es immer verlängert wird, ich meinte einfach das: 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 | time echo 123456
123456
real 0m0.000s
user 0m0.000s
sys 0m0.000s
time echo $(echo 123456)
123456
real 0m0.007s
user 0m0.005s
sys 0m0.002s
time v1=1
real 0m0.000s
user 0m0.000s
sys 0m0.000s
time v1=$(echo 1)
real 0m0.007s
user 0m0.005s
sys 0m0.002s
time v1=$(($v1+100-50*5/5))
real 0m0.000s
user 0m0.000s
sys 0m0.000s
|
Das selbe auch mit printf. Deshalb kann ich '"s="$s"$(printf "foo-%03d-bar\t" $i )"' nicht machen in einer Schleife. Und
| ksl2 () {
echo "0" > /tmp/muell
for i in {1..5}
do
echo -n 3${sensor[i]}000
done > $port2
}
|
Geht auch nicht, das hat aber etwas mit dem tty zu tun, ich kann auch am tty nicht X mal einzeln mit echo etwas senden, das geht dann irgendwie auch wieder länger, aber das hat jetzt mit dem tty zu tun. Es sieht so aus als ob es Zeit kostet die Kommunikation mit tty anzufangen, aber wenn sie mal angefangen wurde braucht es nicht mehr so lange um noch mehr Zeichen zu senden. Edit: Solche Zeilen müssen in einen Codeblock, oder zwischen Backticks: Siehe: '"printf ..."'
Ich hatte das auch versucht bei dem, aber es hat nichts genützt, oder welche Zeichen muss ich verwenden? Diese ' ? Die haben irgendwo geholfen aber bei printf nicht, sah aber grad gut aus.
|