• Willkommen im Linux Club - dem deutschsprachigen Supportforum für GNU/Linux. Registriere dich kostenlos, um alle Inhalte zu sehen und Fragen zu stellen.

If then else bei fehlendem Operator

Hallo Gemeinde,

Ich schreibe gerade an einem kleinen Script welches Zustände auslesen soll, dabei sieht mein Script folgendermaßen aus:
Code:
#/bin/bash
# Status von Adapter 2 (Wiskey Chivas Regal) feststellen:
# Zuerst den Namen auslesen und in die Variable 'ADP2' schreiben:
ADP2="`adapterlist.txt | head -4 | tail -1 | cut -d" " -f3-`"
# Den Zustand der 0,75l Flasche auslesen, die Tabulatorenen entfernen und in die Datei 'adapter2' schreiben:
cat adapterlist.txt | head -5 | tail -1 | sed s'/\t//g' > /tmp/adapter2 ; \
# Zustand der 3,00l Flasche abfragen, die Tabulatorenen entfernen und an die Datei anhaengen:
cat adapterlist.txt | head -6 | tail -1 | sed s'/\t//g' >> /tmp/adapter2  \
# Die If-Anweisung ueberprueft ob der Wert 'voll' ist, dann
if [ `cat /tmp/adapter2 | head -1 | cut -d" " -f3` = "voll" ];
# gibt es die Meldung:
echo "$ADP2 ist VOLL"
# Wenn der Wert nicht 'voll' ist, also irgendwas anderes dann
else
# wird das ausgegeben:
echo "$ADP2 ist leer"
fi
Die Abfrage habe ich nun mehrfach untereinander stehen, der Aufbau ist natürlich identisch und angepasst an die jeweilige Zeilennummer deren Adapter abgefragt werden soll.

Der Inhalt von adapterlist.txt sieht so aus wie weiter unten zu sehen.
Die Ziffern vor den Adaptern (0:) und die Bezeichnung (Art7:) sowie der Name (Weinbrand Mariakron) kann variieren, so könnte der Weinbrand Mariakron auch die Nummer 4: haben. In den Flaschen-Zeilen ändert sich nur der Zustand, der entweder voll oder leer ist:

Code:
0: Art7: Weinbrand Mariakron
	0,75l Flasche: voll
	3,00l Flasche: voll
2: Art6: Wiskey Chivas Regal
	0,75l Flasche: voll
	3,00l Flasche: voll
4: Art4: Wiskey Jim Beam
	0,75l Flasche: leer
	3,00l Flasche: voll
5: Art5: Rotwein Amselfelder
	0,75l Flasche: leer
	3,00l Flasche: voll
6: Art3: Weiswein Pinot Gris
	0,75l Flasche: leer
	3,00l Flasche: voll
7: Art1: Erdbeerschaumwein
	0,75l Flasche: leer
	2,00l Flasche: voll
8: Art0: Underberg
	0,75l Flasche: leer
	3,00l Flasche: voll
3: Art2: Cola
	1,00l Flasche: voll
	2,00l Flasche: voll

Die Datei adapterlist.txt ist nur eine Datei mit der ich teste, aber enthält den Aufbau wie er von einem Programm ausgegeben wird, die Zeilen in denen die Flaschen stehen sind mit einem Tabulator versehen.
Die maximale Anzahl von bis zu acht Adaptern wird hier verwendet, es könnten aber auch weniger oder gar keine vorhanden sein.

Genau da liegt das Problem, die Abfrage arbeitet richtig wenn alle 8 Adapter vorhanden sind und wertet die alle Zustände aus, jedoch kommt bei fehlen aller Adapter das heraus:
Code:
Zeile 13: [: =: Einstelliger (unärer) Operator erwartet.
 ist leer
Wenn mehrere Adapter vorhanden sind, aber ein gerade abgefragter nicht, dann wird das ausgegeben:
Code:
voll ist VOLL

Verschachteltes if then else fi geht ja nicht oder?

Code:
#/bin/bash
if [ -e adapterlist.txt ] then
ADP2="`adapterlist.txt | head -4 | tail -1 | cut -d" " -f3-`"
cat adapterlist.txt | head -5 | tail -1 | sed s'/\t//g' > /tmp/adapter2 ; \
cat adapterlist.txt | head -6 | tail -1 | sed s'/\t//g' >> /tmp/adapter2  \
if [ `cat /tmp/adapter2 | head -1 | cut -d" " -f3` = "voll" ];
echo "$ADP2 ist VOLL"
else
echo "$ADP2 ist leer"
fi
else
echo "Es sind keine Adapter vorhanden"
fi

Wie kann ich die Abfrage bzw. die fehlerhafte Ausgabe verhindern wenn einer, mehrere oder alle Adapter fehlen?

lieben Gruß aus Zuhaus
 
A

Anonymous

Gast
10 Mal durchgelesen und dann erst mal einen großen Schluck aus "ADP2" genommen, und jetzt muss ich mich beeilen sonst kommen meine Freunde mit Perl und Python noch vor mir. ;)

:schockiert: HILFE :schockiert:

Das ist extrem unübersichtlich, schwer zu warten und absolut unflexibel. So ein Fehler ist bei diesem Script nur der Anfang vom Übel.

1. gewöhne dir schnellsten an den Scripttext zu formatieren.
1.1. einrücken von Schleifen und Verzweigungen.
1.2. zusammenhängendes als Block
1.3 Dokumentation ist ja ganz gut, aber wenn du zwischen jeder Zeile einen Kommentar schreibst :zensur: . Wenn das mal wirklich notwendig sein sollte alles zu kommentieren, dann schreib den Kommentar hinter die Befehlszeilen
1.4. Verwende in Scripten die du ins Internet stellst möglichst $( Befehl) und nicht `Befehl` , die Funktion ist genau die selbe, nur das eine ist im Internet nicht auf jedem Rechner und in jeder Schriftart sofort sauber zu erkennen.

2. vermeide soweit möglich unnötige Pipes in der Komandozeile
2.1. " cat| head| tail| cut " machen sed und awk in einer Zeile ohne eine einzige Pipe
2.2 " cat | head | tail | sed " es gilt das gleiche wie unter 2.1


3. wo man mit Pipes arbeiten kann sollte man vermeiden die Zwischenergebnisse in eine temporäre Datei zu schreiben. Alternativ ist eine Variable bei überschaubarem Inhalt 3 x besser. Temporäre Dateien, insbesondere ohne kompletten Path
haben zB extremes Fehlerpotential wenn du nicht 120%sicher gehen kannst, dass alle temporären Dateien zum Programmstart auch wirklich gelöscht sind. Und Dateien, auch wenn es vermeindlich nur temporäre sind löschen bevor man sie geschrieben hat ? ist auch ein Wagnis. es könnte ja durchaus auch mal eine "richtige" Datei mit gleichem Namen existieren. Aus deinem Code zB:
Code:
cat adapterlist.txt | head -5 | tail -1 | sed s'/\t//g' > /tmp/adapter2 ; \
cat adapterlist.txt | head -6 | tail -1 | sed s'/\t//g' >> /tmp/adapter2  \
if [ `cat /tmp/adapter2  ...........

4. Wenn du mehrmals den fast identischen Quelltext hinter einander schreiben musst, solltest du dich dringend mal mit Schleifen befassen.
in deinem Script ändert sich von Adapter zu Adapter nur minimal etwas. Eigentlich nur die Zeilennummer und der Name den du ja sowieso ausließt.

5. Fehler in der Auswertung von Test entstehen immer dann, wenn du nicht sicherstellst das deine Variablen oder Ergebnisse beim Test existieren und auch einen gültigen Wert haben.
Um das sicherzustellen gibt es :
5.1 speichert man entweder die Werte vorher in Variablen oder nutzt nur einen eindeutigen Rückgabewert eine Kommandos zum Verzweigen nach "test"
5.2 oder, wenn über Variablen, dann auch die Variablen vor dem Test prüfen oder besser gleich mit default Werten vorbesetzen wenn nicht sicher ist das dort immer ein Ergebnis eingetragen werden kann, siehe zB "man bash" -> "Parameter Expansion"

6. Wie die "adapterlist.txt" aussieht wissen wir jetzt schon, interessant wäre noch wo sie erzeugt wird und was sich dort ändern könnte.
dann bräuchte man um dir Helfen zu können ein saubers Script aufzusetzen noch was du genau auswerten willst und wie das Ergebnis aussehen soll. Im Moment erschließt sich der Sinn noch nicht, da wohl immer 2 verschieden große Flaschen das sind, du auch beide bearbeitest aber immer nur die erste auszugeben scheinst. :???: (Das Ganze könnte wahrscheinlich mit awk als ein 5-7 Zeiler geschrieben werden, den aber wegen Unmengen an Sonderzeichen so gut wie niemand verstehen kann und deshalb auch der Lerneffekt für dich dann gleich NULL währe) . Deshalb erstellen wir hier die nächsten Tage dann mal ein "SCHÖNES" Bash-Script für dich. Aber nicht "wir" schreiben alles, sondern Du und wir werden dich dabei mit Rat und Hilfe tatkräftig unterstützen. Aber verrate erstmal denn Sinn und wie das Ergebnis genau aussehen soll.

robi
 

framp

Moderator
Teammitglied
robi schrieb:
...und jetzt muss ich mich beeilen sonst kommen meine Freunde mit Perl und Python noch vor mir. ;) ...
Wie Du weisst erzwingt Python Einrückungen ;) Ansonsten habe ich nichts Deiner Antwort hinzuzufügen :thumbs:
 
Hallo robi,

robi schrieb:
10 Mal durchgelesen und dann erst mal einen großen Schluck aus "ADP2" genommen,
:p lecker oder :D

robi schrieb:
und jetzt muss ich mich beeilen sonst kommen meine Freunde mit Perl und Python noch vor mir. ;)
Ich will auch nicht eine andere Sprache lernen nur weil es damit eventuell besser geht, ich wechsle ja auch nicht die Distribution nur weil gerade Linux-Mint "angesagt" ist.
Ich kann noch nicht so viel mit Scripten und dieses ist mein erstes, für mich komplexes Script.
Wenn es darum ginge effektiver zu werden, dann könnte man mir auch gleich sagen ich soll 'C' lernen. Sicher wäre das besser, aber hilft mir nicht.

robi schrieb:
Das ist extrem unübersichtlich, schwer zu warten und absolut unflexibel. So ein Fehler ist bei diesem Script nur der Anfang vom Übel.
Unter anderem deswegen ja auch die vielen Kommentare.
robi schrieb:
1.3 Dokumentation ist ja ganz gut, aber wenn du zwischen jeder Zeile einen Kommentar schreibst :zensur: . Wenn das mal wirklich notwendig sein sollte alles zu kommentieren, dann schreib den Kommentar hinter die Befehlszeilen
Habe ich geändert, steht jetzt hinten dran.
Die Kommentare dienen mir vor allem zum verstehen und lernen, auch um mein bescheidenes Wissen weitergeben zu können wenn es mal soweit ist, denn es gibt viele Anfänger die sich über die genaue Dokumentation freuen.

robi schrieb:
1. gewöhne dir schnellsten an den Scripttext zu formatieren.
1.1. einrücken von Schleifen und Verzweigungen.
1.2. zusammenhängendes als Block
Im Moment sehe ich noch nicht worin der Sinn der Einrückung ist, zumindest mit Syntax-Highlightning ist es auch ohne diese zu erkennen.
Was ist an dem kurzen Ausschnitt meines Scriptes als Block zu verstehen nach Deiner Meinung?
Ich frage deswegen weil ich eben diesen Codeschnipsel als Block ansehen würde, den zu unterteilen wäre dann allenfalls die Differenzierung der if-Anweisung.
Aber wenn es so Brauch ist mach ich das halt auch.

robi schrieb:
1.4. Verwende in Scripten die du ins Internet stellst möglichst $( Befehl) und nicht `Befehl` , die Funktion ist genau die selbe, nur das eine ist im Internet nicht auf jedem Rechner und in jeder Schriftart sofort sauber zu erkennen.
Das habe ich inzwischen geändert, ja es ist tatsächlich besser zu erkennen als dieses kleine "`"

robi schrieb:
2. vermeide soweit möglich unnötige Pipes in der Komandozeile
2.1. " cat| head| tail| cut " machen sed und awk in einer Zeile ohne eine einzige Pipe
Wegen der Verarbeitungsgeschwindigkeit oder weshalb die Reduzierung der Pipes?
Gib mir eine Umsetzung des Befehls und falls nötig einer Erklärung was passiert, denn sonst stehe ich wie oben schon vor der Frage "Warum etwas anderes benutzen wenn ich das andere ja nicht kann?"
awk ist so viel komplexer und schwerer, da ist mir derzeit noch der längere Weg lieber als Wochen und Monate damit zu verbringen das in einer anderen Sprache umzusetzen...gleich 'C' .... ;)

robi schrieb:
3. wo man mit Pipes arbeiten kann sollte man vermeiden die Zwischenergebnisse in eine temporäre Datei zu schreiben.
das hat zB extremes Fehlerpotential wenn du nicht 120%sicher gehen kannst, dass alle temporären Dateien zum Programmstart auch wirklich gelöscht sind
Dem könnte ich ja vorgreifen indem ich /tmp/ von seinen Inhalten befreie bevor das Script die eigentliche Arbeit macht.

robi schrieb:
Code:
cat adapterlist.txt | head -5 | tail -1 | sed s'/\t//g' > /tmp/adapter2 ; \
cat adapterlist.txt | head -6 | tail -1 | sed s'/\t//g' >> /tmp/adapter2  \
if [ `cat /tmp/adapter2  ...........
Du meinst ich sollte diese Werte gleich in eine Variable schreiben anstatt nach /tmp?
Dann klappt aber das aneinander hängen der Einträge nicht mehr oder kann ich eine Variable auch ergänzen?
Code:
VAR1="$( cat adapterlist.txt | head -5 | tail -1 | sed s'/\t//g`)"
VAR2="$( cat adapterlist.txt | head -6 | tail -1 | sed s'/\t//g')"
VAR3="$VAR1+VAR2"
Oder wie sähe Dein Vorschlag aus?

robi schrieb:
in deinem Script ändert sich von Adapter zu Adapter nur minimal etwas. Eigentlich nur die Zeilennummer und der Name den du ja sowieso ausließt.
Konstruktives Beispiel das ich verwenden kann in meinem Script?
Ich bin noch viel am lernen und kann noch nicht so viel, will aber auch etwas erschaffen ohne noch ½ Jahr oder länger lernen zu müssen.

robi schrieb:
5. Fehler in der Auswertung von Test entstehen immer dann, wenn du nicht sicherstellst das deine Variablen oder Ergebnisse beim Test existieren und auch einen gültigen Wert haben.
Ja klar muss und will ich zuvor testen ob die weitere Ausführung des Scripts Sinn macht.
robi schrieb:
5.1 speichert mal entweder die Werte vorher in Variablen oder nutzt nur einen eindeutigen Rückgabewert eine Kommandos zum Verzweigen nach "test"
5.2 Wenn über Variablen, dann auch die Variablen vor dem Test prüfen oder besser gleich mit default Werten vorbesetzen wenn nicht sicher ist das dort immer ein Ergebnis eingetragen werden kann, siehe zB "man bash" -> "Parameter Expansion"
Verstehe eben fast nichts mehr.
Ich kann ja nicht testen ob "adapterlist.txt" existiert weil im Normalfall die Werte über eine Pipe hereinkommen.
Demnach müsste ich ja sowas in der Art machen:
Code:
PROGRAMM PARAMETER 2> /dev/null | head -5 | tail -1 | sed s'/\t//g`
Klappt aber auch nicht wie ich eben feststellen musste.

robi schrieb:
6. Wie die "adapterlist.txt" aussieht wissen wir jetzt schon, interessant wäre noch wo sie erzeugt wird und was sich dort ändern könnte.
Womit ich ja schon wieder 'C' lernen sollte. Maßgebend ist doch die Ausgabe, die ist wie sie ist und ich möchte diese bearbeiten.

robi schrieb:
dann bräuchte man um dir Helfen zu können ein saubers Script aufzusetzen noch was du genau auswerten willst und wie das Ergebnis aussehen soll.
Das Script soll die ausgelesenen Werte mittels Zenity (und/oder Kdialog) grafisch in einer Checklist darstellen.
Dort soll der Benutzer die Werte ändern können und an das Programm zurückgeben.
Das reine auslesen des aktuellen Staus ist ja keine große Sache, aber wenn ich die Werte nicht nur als Text darstellen möchte sondern eben als Checklist, dann ist das kniffliger.
Auch das reine setzen der Werte mitsamt Übergabe an das Programm klappt, nur eben nicht gleichzeitiges anzeigen mit anschließendem ändern.
Mein Script soll gewissermaßen ein Frontend für das Programm sein das den Status aus der Hardware liest bzw. an die Hardware übergibt

robi schrieb:
Im Moment erschließt sich der Sinn noch nicht, da wohl immer 3 Flaschen das sind, du auch beide bearbeitest aber immer nur die erste auszugeben scheinst. :???:
Richtig, es gibt pro Adapter immer drei Zeilen
  • Name
  • Zustand Flasche klein
  • Zustand Flasche groß
Der Zustand der Flasche 2 ist zur Zeit noch nicht notwendig, ich habe ihn nur für spätere Verwendung eingebaut.

robi schrieb:
(Das Ganze könnte wahrscheinlich mit awk als ein 5-7 Zeiler geschrieben werden, den aber wegen unmengen an Sonderzeichen so gut wie niemand verstehen kann und deshalb auch der Lerneffekt für dich dann gleich NULL währe)
Exakt!
robi schrieb:
Deshalb erstellen wir hier die nächsten Tage dann mal ein "SCHÖNES" Bash-Script für dich. Aber nicht "wir" schreiben alles, sondern Du und wir werden dich dabei mit Rat und Hilfe tatkräftig unterstützen. Aber verrate erstmal denn Sinn und wie das Ergebnis genau aussehen soll.
Das Ergebnis dieser Abfrage sollte dann eine ausführbare Datei (in /tmp oder im RAM), also ein weiteres Script sein das so aussieht:

Code:
#/bin/bash
OPT=$(zenity  --list  --width=300 --height=340 --text "Flascheninhalte?" --checklist  --column "Status" --column "Adapter" \
TRUE "Adapter 0" \
TRUE "Adapter 1" \
FALSE "Adapter 2" \
FALSE "Adapter 3" \
TRUE "Adapter 4" \
TRUE "Adapter 5" \
FALSE "Adapter 6" \
FALSE "Adapter 7" \
TRUE "Adapter 8" \
 --separator=":"); echo $OPT > /tmp/opt

# Ausführung:
     for OPT in `cat /tmp/opt | tr ":" "\n"`
     do
     echo "$OPT wurde geleert"
     cat /tmp/opt | tr ":" "\n" > /tmp/opt2
     done

# Erfolgsmeldung wenn angeschlossen:
cat /tmp/opt2 | zenity --list --width=250 --height=305 --column="Zustand von $OPT geändert"

Wobei sich die Werte (True oder False) aus dem hier zu behandelnden Script ergeben sollen.
Sozusagen ein Script das erst aus der Abfrage ein Script erstellt und dieses nach Fertigstellung ausführbar macht und startet.

lieben Gruß aus Hessen
 

framp

Moderator
Teammitglied
Herz-von-Hessen schrieb:
...
robi schrieb:
und jetzt muss ich mich beeilen sonst kommen meine Freunde mit Perl und Python noch vor mir. ;)
Ich will auch nicht eine andere Sprache lernen nur weil es damit eventuell besser geht, ...
Wuerde ich zwar durchaus in Erwaegung ziehen, denn dadurch kann man sich eine Menge Arbeit ersparen - aber mit bash kann man auch alles hinbekommen ;)
robi schrieb:
1. gewöhne dir schnellsten an den Scripttext zu formatieren.
1.1. einrücken von Schleifen und Verzweigungen.
1.2. zusammenhängendes als Block
Im Moment sehe ich noch nicht worin der Sinn der Einrückung ist, zumindest mit Syntax-Highlightning ist es auch ohne diese zu erkennen.
Was ist an dem kurzen Ausschnitt meines Scriptes als Block zu verstehen nach Deiner Meinung?
Ich frage deswegen weil ich eben diesen Codeschnipsel als Block ansehen würde, den zu unterteilen wäre dann allenfalls die Differenzierung der if-Anweisung.
Aber wenn es so Brauch ist mach ich das halt auch.
Vergleiche es mit Punkt, Komma, Gross- und Kleinschreibung Absaetzen und Ueberschriften. Sie dient der leichteren Lesbarkeit und Uebersichtlichkeit von laengeren Texten. Einrueckungen/Indentations haben sich als sehr hilfreich beim Schreiben von Programmen erwiesen. Zu Deiner Frage nach - was ist ein Block -> diese Seite habe ich gefunden wo fuer if, for, und case Beispiele mit Einrueckungen stehen.
Dann klappt aber das aneinander hängen der Einträge nicht mehr oder kann ich eine Variable auch ergänzen?
Code:
VAR1="$( cat adapterlist.txt | head -5 | tail -1 | sed s'/\t//g`)"
VAR2="$( cat adapterlist.txt | head -6 | tail -1 | sed s'/\t//g')"
VAR3="$VAR1+VAR2"
Code:
VAR3="$VAR1 $VAR2"

...Sozusagen ein Script das erst aus der Abfrage ein Script erstellt und dieses nach Fertigstellung ausführbar macht und startet.
Besteht wirklich die Notwendigkeit ausfuehrbaren Code zu generieren? Dadurch schaffst Du eine Indirektion die das Erstellen und Debuggen noch schwerer macht.

Apropos debuggen: Wenn Du nicht alles in einem Befehl machst sondern Zwischenergebnisse in Variablen ablegst kannst Du den Inhat in echo Statements zum Debuggen ausgeben. Geichzeitig auch in Testanweisungen benutzen wie robi schon vorschlug. Oder Du rufst das Scrit mit
Code:
bash -xv SCRIPTNAME
auf und siehst dann welchen Inhalt saemtliche benutzten Variablen im Script haben und kannst darueber herausbekommen, warum Dein Script nicht so tut wie es soll. Auch findet man dadurch meist raus, warum das Script mit einer Syntaxfehlermedlung stirbt
Zeile 13: [: =: Einstelliger (unärer) Operator erwartet.
ist leer[
 
A

Anonymous

Gast
Ok jetzt wird erstmal klar was du machen willst. auch wenn du es uns nicht gerade leicht machst, da du uns nicht genau die Maske lieferst deren Ergebnis du verarbeiten willst.

Aber gehen wir mal systematisch vor, wie man das macht. nutzen wir mal einfach
Code:
0: Art7: Weinbrand Mariakron
   0,75l Flasche: voll
   3,00l Flasche: voll
2: Art6: Wiskey Chivas Regal
   0,75l Flasche: voll
   3,00l Flasche: voll
dieses Format als Vorlage.

Was haben wir:
# eine feste Aufeinanderfolge von NUMMER ARTIKEL und MARKE; und dann 2 Zeilen mit EINHEIT GEFAES und ZUSTAND
dazwischen sind stellenweise noch ":"
# die feste Aufeinanderfolge kann NULL-Mal oder Mehrere-Mal oder eventuell auch sehr oft hintereinander vorkommen.
# alles stehe in einer einzigen Datei.

Lesen wir also mal die Datei genauso aus, legen alles in Variablen und geben diese dann wieder aus, Damit wird erkennen wir ob wir die Datei sauber lesen können, die Werte sauber in die Variablen bekommen

Wir wissen nicht wie oft diese 3 Zeilen vorkommen, also verwenden wie einen Schleife while und lassen diese so lange laufen wie wir die erste Zeile lesen können: lesen tun wir mit "read"
Code:
while read NR ART MK
do
.....
Die gelesenen Werte liegen jetzt in der Schleife in den Variablen NR ART und MK
Als nächstes entfernen wir die ":" und legen diese Werte dann in Aussagekräftige Variablen ab.
Das geht wunderbar mit der Bash und Parameter Expansion, siehe Manpage Bash VAR=${PARAMETER%WERT}
WERT ist dabei das Zeichen das wir am Ende wegschneiden wollen das ":"

Damit ist die erste Zeile schon mal in sauberen Variablen, jetzt müssen wir innerhalb der Schleife noch 2 Zeilen lesen damit wir am Schleifenanfang wieder auf die richtige Anfangszeile kommen.
Wir lesen hier mal vorerst nur alles in eine einzige Variable SCHROTT ein,
Code:
read SCHROTT SCHROTT SCHROTT
das ganze 2 Mal, einmal für jede Zeile, wir wollen nur erstmal die erste Zeile und die prinzipelle Funktion der Schleife testen.

Danach geben wir einfach unsere eingelesenen Variablen in einer Zeile wieder aus, um zu testen ob die Schleife richtig funktioniert.
Code:
echo "$NUMMER  $ARTIKEL   $MARKE"

Jetzt fehlt nur noch wie wir die Datei der Schleife übergeben, es gibt hier 3 Methoden entweder mit einer PIPE am Schleifenanfang
Code:
cat /tmp/DATEI | while ......
oder mit einer Ausgabeumlenkung am Ende der Schleife
Code:
....
done < /tmp/DATEI

oder die dritte Möglichkeit die sich in Anbetracht deines Gesamt-Programmierplanes eventuell in letzter Instanz als die Beste herausstellen könnte, ist folgende.
read (siehe das read in der Manpage bashbuiltins ) ließt ja ohne die Option -u immer vom Standardeingabekanal. Also kannst du auch deinem Script die Daten zB per Pipe übergeben und das read im Script würde dann die Daten lesen die du dem Script per Pipe übergeben hast. Du kannst also das Programm oder Script das bisher die Datei mit den Daten schreibt auch mit einer Pipe die Daten an das Script übergeben lassen.
in diesem Fall einfach die while-schleife mit dem read im Script schreiben und keine Datei per Pipe oder Umleitung an die Schleife übergeben. read ließt dann automatisch aus dem Standard Eingebekanal des Script-Prozesses
Das Script muss aber in diesem Fall dann die Daten auch alle beim ersten lesen verarbeiten, ( das haben wir aber mit dieser while-Schleife sichergestellt.) und dann kann diese temporäre Datei dort ganz entfallen und du kannst das Script aus einem anderem Script heraus mit anderen Programmen kombinieren.

Die 2. Variante ist für den Profi das Angesagtere, die erste Variante wird von Neulingen lieber genommen.
Das ganze Script sieht dann in der 2. Variante im erstem Anlauf so aus.
Code:
while read NR ART MK
 do
   NUMMER=${NR%:}
   ARTIKEL=${ART%:}
   MARKE=${MK}

   read SCHROTT SCHROTT SCHROTT
   read SCHROTT SCHROTT SCHROTT

   echo "$NUMMER  $ARTIKEL   $MARKE"
done < /tmp/DATEI.txt
und liefert bei Schleifendurchlauf mit deinen Daten folgendes Ergebnis
0 Art7 Weinbrand Mariakron
2 Art6 Wiskey Chivas Regal
4 Art4 Wiskey Jim Beam
5 Art5 Rotwein Amselfelder
6 Art3 Weiswein Pinot Gris
7 Art1 Erdbeerschaumwein
8 Art0 Underberg
3 Art2 Cola

bis hier her erst mal, jetzt bist du erstmal dran das nachzuvollziehen und dort versuchen schon mal weiter zu programmieren.

robi
 
A

Anonymous

Gast
Nun würde ich hier gerne weitermachen weil ich nicht weiß wie ich diese Woche noch mal dazukomme, aber du bist wohl noch nicht so weit,
Egal.

Mir fehlen hier ein paar Informationen aber mit meiner Glaskugel kann ich in etwa vermuten was du brauchst.

Das Einlesen der Dateien aus der Datei haben wir ja nun schon fertig, egal wie viele Einträge da jeweils kommen werden sie verarbeitet. Allerdings für das was du brauchst brauchst du das Ergebnis immer in einer bestimmten Reihenfolge, egal wie viele Eingaben Daten dort kommen. Der Wiskey soll also immer in der selben Spalte stehen und nicht ständig wo anders. Die Zahl die wir als NUMMER einlesen wird wohl die Ordnungsnummer sein, auf der dieser Eintrag dann im Ergebnis zu erwarten ist.

Wir brauchen also eine geordnete Ausgabe und um diese zu erhalten brauchen wir eine interne Datenstruktur an der wer wahlfrei arbeiten können und die uns das Ergebnis dann geordnet ausgibt.

An geeignetsten dazu ist ein Array. Das ist eine Sonderform der Variablen und man kann es sich vorstellen wie einen Schrank mit lauter Schubfächern und jedes Schubfach hat eine von 0 bis 100.... als Ordnungsnummer. Wir brauchen dann nur zu sagen "Schrank1->Fach3" oder in den meisten Programmiersprachen geschrieben "Schrank1[ 3 ]"
Schön währe hier ein mehrdimensionales Array aber das gibt's in der Bash nicht. also benutzen wir mehrere eindimensionale eines für den Markennamen und je eines für den Zustand der Flaschen.

Damit wir keine Problem bekommen mit Daten die nicht in der Eingabe enthalten sind, belegen wir die 3 Arrays mit gültigen default Daten vor.

Dazu nutzen wir eine Zählschleife wie sie in fast jeder Programmiersprache vorhanden ist, die for-Schleife. und lassen diese eine Index (nennen wir in "i" das ist überall so gebräuchlich) von 0 bis 9 zählen. Mit diesem Index sprechen wir die einzelnen Variablen dann in der Schleife an und weisen gültige Werte zu, und belegen so die Arrays vor. (Nachzulesen Array und for-Schleife in der Manpage von Bash)
Die Arrays nennen wir AMN für den ArrayMarkenName und AGF und AKF für die ArrayGroßeFlasche und ArrayKleineFlasche

Code:
for (( i=0 ; i<10 ; i++ ))
  do
     AMN[ $i ]="unbenutzt"               # MarkenName
     AGF[ $i ]="leer"                    # GroßeFlasche
     AKF[ $i ]="leer"                    # KleineFlasche
done

Ausgeben tun wir die Daten dann auch in einer For-Schleife
Code:
for (( i=0 ; i<10 ; i++ ))
  do
     echo  " ${AMN[ $i ]} :  ${AGF[ $i  ]} :  ${AKF[ $i ]}"
done

So jetzt haben wir schon 3 Blöcke , Die Initialisierung , das Einlesen der Dateien, und die Ausgabe,
es fehlt also nur noch die Verarbeitung. und diese muss hier in der Schleife beim Einlesen und zwar müssen die Daten entsprechend von NUMMER richtig in die 3 Arrays eingelesen werden
Code:
AMN[ $NUMMER]="$MARKE"                            # Vorsicht Leerzeichen möglich
AGF[ $NUMMER]=$ZUSTAND1
AKF[ $NUMMER]=$ZUSTAND2

Als nächstes machen wir was ganz verrücktes, wie fassen mal all unsere Bausteine in einem einzigem Script zusammen
Code:
# Initialisierung der Arrays
for (( i=0 ; i<10 ; i++ ))
  do
     AMN[ $i ]="unbenutzt"               # MarkenName
     AGF[ $i ]="leer"                    # GroßeFlasche
     AKF[ $i ]="leer"                    # KleineFlasche
done

# Einlesen der Daten aus /tmp/DATEI.txt
while read NR ART MK
 do
    NUMMER=${NR%:}
    ARTIKEL=${ART%:}
    MARKE=${MK}

    # Einlesen der Flaschendaten
    read GROESSE1 FLASCHE1 ZUSTAND1
    read GROESSE2 FLASCHE2 ZUSTAND2

    # Einsortieren der Daten in die Arrays
    AMN[ $NUMMER]="$MARKE"                            # Vorsicht Leerzeichen möglich
    AGF[ $NUMMER]=$ZUSTAND1
    AKF[ $NUMMER]=$ZUSTAND2

done < /tmp/DATEI.txt

# Datenausgabe
for (( i=0 ; i<10 ; i++ ))
  do
     echo  " ${AMN[ $i ]} :  ${AGF[ $i  ]} :  ${AKF[ $i ]}"
done
Du musst natürlich deine Eingabedatei anpassen
So dann starten wir das mal und erhalten
Weinbrand Mariakron : voll : voll
unbenutzt : leer : leer
Wiskey Chivas Regal : voll : voll
Cola : voll : voll
Wiskey Jim Beam : leer : voll
Rotwein Amselfelder : leer : voll
Weiswein Pinot Gris : leer : voll
Erdbeerschaumwein : leer : voll
Underberg : leer : voll
unbenutzt : leer : leer
Mal nur bis hier her. Was hat sich zu deinem Quelltext geändert ;)
  • # keine Befehlsverkettungen und Subprozesse die über Pipe miteinander arbeiten müssen
    # Kein mehrfaches Auslesen ein und der selben Datei
    # Keine weiteren Dateien als Zwischenspeicher
    # Wir benutzen bis hier hin nur Funktionen die in der Bash selbst schon vorhanden sind
    # Das Script ist sauber strukturiert und mit wenigen Kommentaren selbsterklärend
    # Der Fehler den du hattest und einige mehr auf die du noch gestoßen wärst können gar nicht entstehen
    # Das Script ist wesentlich flexibler und lässt sich schnell an alles mögliche anpassen
    # Das Script ist bedeutend kürzer und 10 Mal besser verständlich wie deines vom Anfang

An dieser Stelle kannst du jetzt weitermachen, und die eventuellen fehlenden Funktionen einbauen und die Ausgabe anpassen. (Und den Fehler suchen den ich "unbeabsichtigt" eingebaut habe, Schau mal nach der Benennung der Arrays und welche Daten da gespeichert werden ;) ) Was du festellen wirst, obwohl ich das Script geschrieben habe, wirst du dich schnell darin zurecht finden und problemlos solche Fehler beheben können.
Was du bis hier hin jedoch erkennen solltest, wie man an die Lösung eines Problems herangeht und wie ein "schönes" Script entsteht.

robi
 
Hallo robi,

robi schrieb:
Ok jetzt wird erstmal klar was du machen willst. auch wenn du es uns nicht gerade leicht machst, da du uns nicht genau die Maske lieferst deren Ergebnis du verarbeiten willst.
Das cli-Programm steuern, genau, dieses gib mir die auszulesende Datei vor. und ehe ich es vergesse, auch wenn es wahrscheinlich keine große Rolle spielt. es können bis zu 9 Adaptern statt 8 sein.
Macht der Schleife ja keinen Abbruch oder?

robi schrieb:
Aber gehen wir mal systematisch vor, wie man das macht. nutzen wir mal einfach
dieses Format als Vorlage.
Die letzten beiden Zeilen sind durch Tabulatoren eingerückt und nicht durch Leerzeichen ansonsten ja.

robi schrieb:
Was haben wir:
# eine feste Aufeinanderfolge von NUMMER ARTIKEL und MARKE; und dann 2 Zeilen mit EINHEIT GEFAES und ZUSTAND
dazwischen sind stellenweise noch ":"
# die feste Aufeinanderfolge kann NULL-Mal oder Mehrere-Mal oder eventuell auch sehr oft hintereinander vorkommen.
# alles stehe in einer einzigen Datei.
Exakt, außer das die Eingabe über eine Pipe kommt.
Auf dem PC auf welchem ich das Script schreibe habe ich diese Adapter nicht, schon gar nicht alle 9 möglichen und deshalb wird mit der Datei gearbeitet.
Wobei ich sogar annehme das es kein Gerät gibt das wirklich alle diese Schnittstellen hat, das nur am Rande.
Vorgabe ist, das Script soll laufen, egal ob mit einem, keinem, zwei oder noch mehr Adaptern.

robi schrieb:
Wir wissen nicht wie oft diese 3 Zeilen vorkommen, also verwenden wie einen Schleife while und lassen diese so lange laufen wie wir die erste Zeile lesen können: lesen tun wir mit "read"
Code:
while read NR ART MK
do
.....
Klingt weniger kompliziert als mein bisheriger Lösungsweg um die Anzahl der Adapter zu ermitteln, der war nämlich folgender:
Code:
SUMME="`cat adapterlist.txt | wc -l`"

bc -l <<< "$SUMME/3" | cut -d"." -f1 > /tmp/anzahl
OPT="`cat /tmp/anzahl`"
Ich gebe aber zu das eine Schleife sinnvoller ist, vor allem weil unabhängig von der Anzahl der Adapter :)

robi schrieb:
Die gelesenen Werte liegen jetzt in der Schleife in den Variablen NR ART und MK
Das bedeutet also, nur damit ich das richtig verstehe: die Bash nimmt automatisch jedes "nicht sichtbare" Zeichen (Space, Tab) als Feldtrennung?
Nein...weil auch der Name Leerstellen haben kann :???:

EDIT Anfang:
Aah, es sind 3 Spalten angegeben, ergo wird alles was ab der dritten Spaten kommt in der letzten Variablen aufgenommen, verstanden
Edit Ende.

Da kann ich mir die ganze Geschichte mit cut ja ersparen :D
Ich muss also nur für jede Spalte einen Variablennamen vergeben um jeden Wert in eine solche einzulesen? Geil!

robi schrieb:
Als nächstes entfernen wir die ":" und legen diese Werte dann in Aussagekräftige Variablen ab.
Das geht wunderbar mit der Bash und Parameter Expansion, siehe Manpage Bash VAR=${PARAMETER%WERT}
Das ersetzt dann mein tr -d ":" "" :)

robi schrieb:
das ganze 2 Mal, einmal für jede Zeile, wir wollen nur erstmal die erste Zeile und die prinzipelle Funktion der Schleife testen.
O.K., alles zwischen while und done ist Schleifenablauf der in chronologischer Reihenfolge abläuft.
Code:
PROGRAMM PARAMETER (aka. cat adapterlist.txt) | while read SCHROTT SCHROTT SCHROTT
read GROESSE GEFAESS FUELLSTAND
read NR ART MK
würde die Spalten der erste Zeile komplett in die Variable SCHROTT legen.
Die zweite Zeile in die Variablen GROESSE GEFAESS und FUELLSTAND
sowie die Dritte in NR ART MK.
Also wird in der Schleife, genau wie im Script immer von oben nach unten gearbeitet!?
BTW. ich habe früher auf dem Atari ST Hypertexte im ST-Guide Format (kennt das jemand hier) geschrieben, da gab es eine, wie ich finde, sehr sehr nützliche Funktion, nämlich include, damit konnte man in den behandelnden Text externe Textteile an der entsprechenden Stelle einbauen.
Da machte die Sache wesentlich übersichtlicher als "nur" Einrückungen, geht bei Bash oder allgemein bei Script-Sprachen wohl nicht?

robi schrieb:
Danach geben wir einfach unsere eingelesenen Variablen in einer Zeile wieder aus, um zu testen ob die Schleife richtig funktioniert.
Code:
echo "$NUMMER  $ARTIKEL   $MARKE"
Woher weiß denn die Schleife nun das nur jeweils jede 3. Zeile gelesen werden soll, doch nur dadurch das zweimal read SCHROTT SCHROTT SCHROTT darunter stehen richtig! Habe es eben mal versucht, verstehe es jetzt.
Will ich einer Schleife mitteilen jeweils drei Zeilen als "Paket" zu behandeln muss ich auch drei Zeilen read einbauen. :D

robi schrieb:
Jetzt fehlt nur noch wie wir die Datei der Schleife übergeben, es gibt hier 3 Methoden entweder mit einer PIPE am Schleifenanfang
Code:
cat /tmp/DATEI | while ......
oder mit einer Ausgabeumlenkung am Ende der Schleife
Code:
....
done < /tmp/DATEI
Die Pipe war tatsächlich der erste Weg der mir eingefallen ist, liegt ja auch nahe.
Die Ausgabeumlenkung birgt aber dann die Gefahr das der Dateiname sich ändern könnte und somit nichts mehr funktioniert, zudem kann ich ja nicht die Ausgabe des Programms welches die adapterlist.txt liefert so einbinden. So bliebe nur die Pipe oder:

robi schrieb:
oder die dritte Möglichkeit ....
read (siehe das read in der Manpage bashbuiltins ) ließt ja ohne die Option -u immer vom Standardeingabekanal. Also kannst du auch deinem Script die Daten zB per Pipe übergeben und das read im Script würde dann die Daten lesen die du dem Script per Pipe übergeben hast. Du kannst also das Programm oder Script das bisher die Datei mit den Daten schreibt auch mit einer Pipe die Daten an das Script übergeben lassen.
Wie oben
PROGRAMM PARAMETER | SCRIPT.sh
oder direkt im Script:
Code:
#!/bin/bash

PROGRAMM PARAMETER

while read....

Oder ein
Code:
#!/bin/bash

while read....
....
done < PROGRAMM OPTION
Wobei das Script dann mit einem blinkenden Cursor stehen bleibt sogar wenn ich nach dem done noch ein exit 0 schreibe, warum?
Bleibt dann doch nur die direkte Pipe vom Programm zum Script oder der Umweg über eine Datei.

robi schrieb:
Die 2. Variante ist für den Profi das Angesagtere, die erste Variante wird von Neulingen lieber genommen.
Bin ertappt :eek:ps:

Das ganze Script sieht dann in der 2. Variante im erstem Anlauf so aus.
Code:
while read NR ART MK
 do
   NUMMER=${NR%:}
   ARTIKEL=${ART%:}
   MARKE=${MK}
Die Variablen lauten NR ART MK, was machen dann nun die drei Zeilen NUMMER ARTIKEL MARKE, die Worte erscheinen ja gar nicht in der Ausgabe. (Müssen sie ja auch nicht, ich brauch ja erstmal nur den Namen und den Füllstand aus der kleinen Flasche.

Mein Script arbeitet in Verbindung mit Zenity auch schon nur das ich zwar den Füllstand ändern kann, aber nicht vorher weiß wie dieser gerade ist.

Code:
#!/bin/bash
function menu {

AUSWAHL=$( zenity --list --radiolist --width=650 --height=250 --text "Welche Flaschen möchten Sie bearbeiten?" --title "Status" --column="" --column Punkt --column Möglichkeiten \
\"\" Alle_schließen                       "Alle Flaschen schließen" \
\"\" Einige_schließen                     "Eine Auswahl treffen" \
\"\" Alle_öffnen                    "Alle Flaschen öffnen" \
\"\" Einige_öffnen                  "Eine Auswahl treffen" \
\"\" Status                             "Den aktuellen Status aller vorhandenen Flaschen anzeigen" \
\"\" Lizenz                             "Die Lizenzbestimmungen und den Versions-Hinweis anzeigen" \
)


if [ -z "$AUSWAHL" ];then
        zenity --info --text "Barkeeper wird beendet, danke für die Benutzung"

    elif [ "$AUSWAHL" = Alle_schließen ];then
        auswahl_alle_schließen
    elif [ "$AUSWAHL" = Einige_schließen ];then
        auswahl_einige_schließen
    elif [ "$AUSWAHL" = Alle_öffnen ];then
        auswahl_alle_entsperren
    elif [ "$AUSWAHL" = Einige_öffnen ];then
        auswahl_einige_öffnen
    elif [ "$AUSWAHL" = Lizenz ];then
        auswahl_lizenz
    elif [ "$AUSWAHL" = Status ];then
        auswahl_status

fi

}
.................. dazwischen sind die anderen Auswahlmöglichkeiten...........
...
function auswahl_einige_schließen {

OPT=$(zenity  --list  --width=300 --height=340 --text "Welche Adapter möchten Sie schließen?" --checklist  --column "Status" --column "Auswahlmöglichkeiten" \
TRUE "Weinbrand Mariakron" \
TRUE "Wiskey Chivas Regal" \
FALSE "Wiskey Jim Beam" \
FALSE " Rotwein Amselfelder" \
TRUE "Weiswein Pinot Gris" \
TRUE "Erdbeerschaumwein" \
FALSE "Underberg" \
FALSE "Cola" \
TRUE "Wasser" \

 --separator=":"); echo $OPT > /tmp/opt

        for SELECTION in `echo $OPT | tr ":" "\n"`
        do
        barkeeper close $SELECTION
        done
Das ist nur ein Ausschnitt des Ganzen Projekts.
Ich muss also im Moment in der Mehrfachauswahl entscheiden ob ich schließen oder öffnen will, dabei noch zwischen alle und einige unterscheiden, alles ohne zu wissen wie der Status eigentlich ist.
Klappt schon, aber um es auch auf die Menschheit los zulassen ist es, so empfinde ich es, eher umständlich.
Wenn ich programmieren könnte würde ich wohl das Programm selbst verändern statt darauf aufzusetzen.
Aber mich mit 'C' zu befassen wo ich die Bash noch nichtmal richtig ausreize wäre doch wie reiten bevor man laufen kann :/
Ein Feld das den Zustand anzeigt und den Benutzer diesen dann beeinflussen lässt, das ist mein Ziel.
Wenn dabei der Zustand noch im Hintergrund automatisch überwacht würde und bei einer Änderung desselben ein Hinweis erscheint (Taskleisten Noticication) wäre das wohl perfekt.

robi schrieb:
bis hier her erst mal, jetzt bist du erstmal dran das nachzuvollziehen und dort versuchen schon mal weiter zu programmieren.
Vielen Dank!
Ich werde die gewonnenen Erkenntnisse umsetzen sobald ich dazu komme und dann hier berichten.

lieben Gruß aus Hessen
 
Hallo framp,

framp schrieb:
Herz-von-Hessen schrieb:
Ich will auch nicht eine andere Sprache lernen nur weil es damit eventuell besser geht, ...
Wuerde ich zwar durchaus in Erwaegung ziehen, denn dadurch kann man sich eine Menge Arbeit ersparen - aber mit bash kann man auch alles hinbekommen ;)
Vor vielen Jahren habe ich mal "Pure C" probiert, aber wohl nicht ernsthaft genug.

framp schrieb:
Vergleiche es mit Punkt, Komma, Gross- und Kleinschreibung Absaetzen und Ueberschriften.
Mache ich, sobald ich verstehe wo und wann man wie weit einrückt

framp schrieb:
Sie dient der leichteren Lesbarkeit und Uebersichtlichkeit von laengeren Texten. Einrueckungen/Indentations haben sich als sehr hilfreich beim Schreiben von Programmen erwiesen. Zu Deiner Frage nach - was ist ein Block -> diese Seite habe ich gefunden wo fuer if, for, und case Beispiele mit Einrueckungen stehen.
Ich denke das meine Beiträge sonst eigentlich auch übersichtlich und gut lesbar sind, werde mich also Bemühen aus Deinem Link die Regel zu beziehen, danke dafür.

framp schrieb:
Code:
VAR3="$VAR1 $VAR2"
Code:
# VAR1="Welt"
# echo $VAR1
Welt
# VAR2="Hallo"
# echo $VAR2
Hallo
# VAR3="$VAR1 $VAR2"
# echo $VAR3
Welt Hallo
# echo $VAR3 $VAR2 $VAR1
Welt Hallo Hallo Welt
Danke, also würden damit die Werte hintereinander in einer Zeile auftauchen, muss dann noch ein:
Code:
echo $VAR3  $VAR2 $VAR1 | tr " " "\12"
anhängen.

framp schrieb:
Besteht wirklich die Notwendigkeit ausfuehrbaren Code zu generieren? Dadurch schaffst Du eine Indirektion die das Erstellen und Debuggen noch schwerer macht.
Natürlich könnte ich die Ausgabe des Programms auch nur so darstellen wie diese in der adapterlist.txt stehen, zufrieden macht es mich aber nicht.

framp schrieb:
Code:
bash -xv SCRIPTNAME
auf und siehst dann welchen Inhalt saemtliche benutzten Variablen im Script haben und kannst darueber herausbekommen, warum Dein Script nicht so tut wie es soll.
Gute Funktion :)

framp schrieb:
Auch findet man dadurch meist raus, warum das Script mit einer Syntaxfehlermedlung stirbt
Zeile 13: [: =: Einstelliger (unärer) Operator erwartet.
ist leer[
Weil das Programm nur mit root-Rechten läuft und ich es als User ausführte, konnte die Variable nicht gefüllt werden und war bei der nächsten Verwendung leer was dann diesen Fehler verursachte.
Ich habe also eine Passwortabfrage eingebaut, aber in Verbindung mit Zenity klappt das nicht so wie gewünscht.
Die Passwortabfrage will ich ja nicht vor jeden Befehl schreiben sondern, wie auch in Deinem collectNWdata.sh nur einmal machen müssen.

lieben Gruß aus Hessen
 

framp

Moderator
Teammitglied
Herz-von-Hessen schrieb:
...
framp schrieb:
Vergleiche es mit Punkt, Komma, Gross- und Kleinschreibung Absaetzen und Ueberschriften.
Mache ich, sobald ich verstehe wo und wann man wie weit einrückt...
Eine Menge lernt man, wenn man sich schon existierenden bash Code ansieht und auch sich den Advanced Scripting Guide zu Gemüte führt.

...
framp schrieb:
Sie dient der leichteren Lesbarkeit und Uebersichtlichkeit von laengeren Texten. Einrueckungen/Indentations haben sich als sehr hilfreich beim Schreiben von Programmen erwiesen. Zu Deiner Frage nach - was ist ein Block -> diese Seite habe ich gefunden wo fuer if, for, und case Beispiele mit Einrueckungen stehen.
Ich denke das meine Beiträge sonst eigentlich auch übersichtlich und gut lesbar sind, werde mich also Bemühen aus Deinem Link die Regel zu beziehen, danke dafür...
Ich bin immer gerne bereit bei Code zu helfen - aber wenn ich ein Programm sehe, dass keinerlei Einrueckungen hat und kryptische Variablennamen hat, d.h. es mich viel zu viel Zeit kostet den Code zu verstehen - obwohl das bei vernünftiger Wahl von Variablennamen und Einrückungen möglich wäre - sehe ich mir das erst gar nicht an. Genauso mache ich es mit Postings wo alles kleingeschrieben wurde und weder Punkt noch Komma und Absätze benutzt werden :)
framp schrieb:
Code:
VAR3="$VAR1 $VAR2"
Code:
# VAR1="Welt"
# echo $VAR1
Welt
# VAR2="Hallo"
# echo $VAR2
Hallo
# VAR3="$VAR1 $VAR2"
# echo $VAR3
Welt Hallo
# echo $VAR3 $VAR2 $VAR1
Welt Hallo Hallo Welt
Danke, also würden damit die Werte hintereinander in einer Zeile auftauchen, muss dann noch ein:
Code:
echo $VAR3  $VAR2 $VAR1 | tr " " "\12"
anhängen.
Warum nicht
Code:
echo "$VAR3  $VAR2 $VAR1 \x12"
, sofern \12 der Hexwert für FormFeed sein soll.

...
framp schrieb:
Besteht wirklich die Notwendigkeit ausfuehrbaren Code zu generieren? Dadurch schaffst Du eine Indirektion die das Erstellen und Debuggen noch schwerer macht.
Natürlich könnte ich die Ausgabe des Programms auch nur so darstellen wie diese in der adapterlist.txt stehen, zufrieden macht es mich aber nicht.
Du musst bedenken: Du erstellst und debugst Dein Generierungs bash - und dann musst Du noch mal den generierten Code debuggen. Ich würde das nur in einem Script machen. Ansonsten benötigst Du wesentlich mehr Zeit bis es läuft.
 
Nochmal Hallo robi,

robi schrieb:
Nun würde ich hier gerne weitermachen weil ich nicht weiß wie ich diese Woche noch mal dazukomme, aber du bist wohl noch nicht so weit,
Egal.
Keine Angst, ich habe es nicht so eilig das ich das Projekt in dieser Woche bereits fertigstellen könnte und wollte.
Ich möchte das "Programm" möglichst so gestalten das es auf jeder Distribution und jedem Desktop lauffähig ist und deshalb aus Kompatibilitätsgründen sowohl eine Version mit Zenity als auch mit Kdialog bauen,
Es ist somit auch nächste Woche dazu noch Zeit.

robi schrieb:
aber mit meiner Glaskugel kann ich in etwa vermuten was du brauchst.
gut poliert hat man damit Durchblick ;)

robi schrieb:
Allerdings für das was du brauchst brauchst du das Ergebnis immer in einer bestimmten Reihenfolge, egal wie viele Eingaben Daten dort kommen.
Der Wiskey soll also immer in der selben Spalte stehen und nicht ständig wo anders.
Darüber habe ich noch gar nicht nachgedacht, das die Einträge ja an unterschiedlichen Stellen stehen würden.
Aber da hast Du schon Recht, es wäre besser.
Selbst habe ich nur einen solchen Adapter (per USB) und kann gar nicht genau sagen ob sich die Reihenfolge ändern würde hätte ich mehrere davon.

robi schrieb:
An geeignetsten dazu ist ein Array. Das ist eine Sonderform der Variablen und man kann es sich vorstellen wie einen Schrank mit lauter Schubfächern und jedes Schubfach hat eine von 0 bis 100.... als Ordnungsnummer. Wir brauchen dann nur zu sagen "Schrank1->Fach3" oder in den meisten Programmiersprachen geschrieben "Schrank1[ 3 ]"
Ich nehme mal an das die Anzahl der "normalen" Variablen ebenso beliebig sein darf wie die bei Ports für irgendwelche Dienste - Nur durch den RAM begrenzt.

robi schrieb:
Schön währe hier ein mehrdimensionales Array aber das gibt's in der Bash nicht. also benutzen wir mehrere eindimensionale eines für den Markennamen und je eines für den Zustand der Flaschen.
Unter einem "mehrdimensionales Array" kann ich mir gerade auch nichts vorstellen, verarbeite ich doch gerade noch die Variablen :roll:
Da habe ich mir ja ein Ziel gesetzt das mein Hirnschmalz fordert.

robi schrieb:
Damit wir keine Problem bekommen mit Daten die nicht in der Eingabe enthalten sind, belegen wir die 3 Arrays mit gültigen default Daten vor.
unbenutzt oder leer?

robi schrieb:
Dazu nutzen wir eine Zählschleife wie sie in fast jeder Programmiersprache vorhanden ist, die for-Schleife.
Die arbeitet eine Auflistung zeilenweise durch also z.B. for i in ls -1|grep 'txt$' do...
Was mit ls ohne -1 nicht gehen würde.

robi schrieb:
Die Arrays nennen wir AMN für den ArrayMarkenName und AGF und AKF für die ArrayGroßeFlasche und ArrayKleineFlasche
So jetzt haben wir schon 3 Blöcke , Die Initialisierung , das Einlesen der Dateien, und die Ausgabe,
Nachvollziehbare Namen.

robi schrieb:
Als nächstes machen wir was ganz verrücktes, wie fassen mal all unsere Bausteine in einem einzigem Script zusammen
Du musst natürlich deine Eingabedatei anpassen
Natürlich.
So sieht das aus wenn ich das Script am PC mit einem Adapter benutze:
Code:
barkeeper liste | ./adapter1.sh
 Weinbrand Mariakron :  voll :  voll
 unbenutzt :  leer :  leer
 unbenutzt :  leer :  leer
 unbenutzt :  leer :  leer
 unbenutzt :  leer :  leer
 unbenutzt :  leer :  leer
 unbenutzt :  leer :  leer
 unbenutzt :  leer :  leer
 unbenutzt :  leer :  leer
 unbenutzt :  leer :  leer
Das muss ich dann "nur" noch in einen zenity/Kdialog Diolog zur Auswahl formatieren.
Um wie viel kürzer der Code so ist, einfach genial :)

robi schrieb:
Mal nur bis hier her. Was hat sich zu deinem Quelltext geändert ;)
  • # keine Befehlsverkettungen und Subprozesse die über Pipe miteinander arbeiten müssen
    # Kein mehrfaches Auslesen ein und der selben Datei
    # Keine weiteren Dateien als Zwischenspeicher
    # Wir benutzen bis hier hin nur Funktionen die in der Bash selbst schon vorhanden sind
    # Das Script ist sauber strukturiert und mit wenigen Kommentaren selbsterklärend
    # Der Fehler den du hattest und einige mehr auf die du noch gestoßen wärst können gar nicht entstehen
    # Das Script ist wesentlich flexibler und lässt sich schnell an alles mögliche anpassen
    # Das Script ist bedeutend kürzer und 10 Mal besser verständlich wie deines vom Anfang
Zeitersparnis durch Punkt 1 und 2
Build in Kommandos, wenn man die einsetzen kann sind echt toll.
Stimmt, es ist erheblich übersichtlicher.
Das man mit Variablen & Arrays Fehler, vor allem Tippfehler vermeidet ist offensichtlich.
Für flexiblere Anpassungen fehlen mir gerade die Ideen.
Jetzt erahne ich wieso Programme unter Linux so klein und effizient sind.

robi schrieb:
An dieser Stelle kannst du jetzt weitermachen, und die eventuellen fehlenden Funktionen einbauen und die Ausgabe anpassen.
Mache ich.
robi schrieb:
(Und den Fehler suchen den ich "unbeabsichtigt" eingebaut habe, Schau mal nach der Benennung der Arrays und welche Daten da gespeichert werden ;) )
Na hoffentlich tritt der Fehler nicht nur auf wenn es nur ein "Trockenlauf" mit der Datei ist sondern auch mit dem Programm.
Mal sehen ob ich den heute Nacht wenn ich heim komme finde :/

robi schrieb:
Was du festellen wirst, obwohl ich das Script geschrieben habe, wirst du dich schnell darin zurecht finden und problemlos solche Fehler beheben können.
Was du bis hier hin jedoch erkennen solltest, wie man an die Lösung eines Problems herangeht und wie ein "schönes" Script entsteht.
Richtig, ich muss mir vorher viel genauer überlegen was in welcher Reihenfolge drankommen muss und welche Mittel geeignet sind.
Werde heute N8 nochmal darauf eingehen, muss jetzt bald weg.

lieben Gruß aus Hessen
 
Oben