Anfänger-Frage zur shell-Programmierung
-
Hallo,
ich muss ein shell-script schreiben (bash) welches alle Positionsparameter durchnummeriert ausgibt.
Hier mal mein Ansatz:#!/bin/bash set ABC xxx 123 X=1 for I in $(seq 10): do echo Pos-Paramter $I [?????????] X=$[$X+1] done
Mein Problem ist nun, dass ich nicht so richtig weiss, was ich beim [???] schreiben soll.
Ich habe dabei folgenden Gedankengang:
$1 gibt aus 'ABC', $2 'xxx' und $3 '123'
Wenn ich das in der shell direkt tippe alles okay.
Nun würde ich gerne an der Stelle der [????] etwas schreiben wie [I] oder so.
Also den Schleifen-Zähler als Wert an das $-Zeichen übergeben. Aber das funktioniert leider nicht. Habe es auch mit pipes | versucht, aber das erwartet ja komplette Befehle.
Hat da jemand einen Vorschlag, wie ich quasi einen Variablen-Wert an das $-Zeichen hängen kann ?Gruss,
Lalas
-
Du hast die for-Schleife der Bash nicht verstanden.
Der Variablen $I wird nacheinander die Werte nach dem "in" zugewiesen. Jetzt musst du nurnoch die übergebenen Parameter der for-Schleife anhängen. Das machst du mir $@ (bzw. $*).
Also:
for I in $@
Und rechnen musst du mit expr, zum Beispiel so:
`expr $var + 1`
-
Okay, dass hat mir schonmal geholfen bezgl. der for-schleife.
Wie sieht es denn aus bezgl. der anderen Sache, da jemand eine Idee ?
-
ich will nochmal schieben....
Hat jemand noch einen Tipp zu diesem Thema ?
Gruss,
Lalas
-
lalas schrieb:
Hallo,
ich muss ein shell-script schreiben (bash) welches alle Positionsparameter durchnummeriert ausgibt.
Hier mal mein Ansatz:keine Ahnung, was du mit Positionsparameter meinst. Wenn du aber alle Argumente der Reihe nach durchnummeriert haben willst, dann bietet sich das hier an:
#!/bin/sh counter=1 echo "0: $0" while test $# -ne 0 ; do echo "${counter}: $1" let counter++ shift 1 done
Ausgabe:
$ ./a.sh a b c d e f e g h 0: ./a.sh 1: a 2: b 3: c 4: d 5: e 6: f 7: e 8: g 9: h
-
[edit]: ah habe grad was entdeckt in deinem code; ich muss also geschweifte Klammern {} nutzen um den Variablenwert an das $ zu "hängen" ich probiere es damit mal...
Danke für die Antwort.
Positionsparameter ist ein Begriff unseres Dozenten, gemeint ist folgendes:
set ABC 123 XXX echo PosParamter 1: $1 echo PosParamter 2: $2 echo PosParamter 3: $3
Dann ist die Ausgabe entsprechend:
PosParamter 1: ABC
PosParamter 2: 123
PosParamter 3: XXXecho $# liefert übrigens den letzten Zeichenblock, echo $@ gibt alle Blöcke aus.
Und die Aufgabe lautet einfach:
"Schreiben Sie ein shell-script, das ALLE Positionsparamter mit Nummerierung ausgibt."
Meine Idee war also, eine Schleife zu programmieren und den Schleifenzähler quasi als Nummer für den $-Befehl zu verwenden.Also erster Schleifendurchlauf (Zähler=1) --> echo $1
zweiter Durchlauf (Zähler=2) --> echo 2
usw.
Da der Schleifenzähler nicht wie beim klassischen Programmieren weitergenutzt werden kann (ich bekomme es zumindest nicht hin), habe ich es halt mit einer weiteren Variablen versucht, die ich mit X=1 initialisiere und dann nach jeder Ausgabe in der Schleife inkrementiere.Ich hoffe ihr könnt mir nun folgen
-
lalas schrieb:
echo $# liefert übrigens den letzten Zeichenblock, echo $@ gibt alle Blöcke aus.
Die erste Aussage stimmt nicht. $# liefert die Anzahl der Argumente, die dem Skript übergeben wird. Vergleichbar mit
argc - 1
in der C Sprache, denn $# ist 0, wenn keine Parameter übergeben werden. Die 2. Aussage stimmt aber.lalas schrieb:
Und die Aufgabe lautet einfach:
"Schreiben Sie ein shell-script, das ALLE Positionsparamter mit Nummerierung ausgibt."mein Vorschlag tut genau das.
lalas schrieb:
Meine Idee war also, eine Schleife zu programmieren und den Schleifenzähler quasi als Nummer für den $-Befehl zu verwenden.
soweit ich mich erinnern kann, kann man in bash keine 2fache Auswertung machen, also sowas wie
VAR1=hallo hallo=welt echo ${${VAR1}}
Denn das endet in
bash: ${${VAR1}}: bad substitution
-
supertux schrieb:
#!/bin/sh counter=1 echo "0: $0" while test $# -ne 0 ; do echo "${counter}: $1" let counter++ shift 1 done
Danke nochmal, ich hätte noch eine Fragen zu deinem code;
test $# -ne 0
Du prüfst ob $# (Anzahl der Argumente) ungleich 0 ist. Warum läuft die Schleife nicht endlos bzw. wo ist die Abbruchbedingung ? Die Anzahl der übergebenen Argumente verändert sich doch nicht während die Schleife durchläuft...
Ich will nämlich noch eine Fehlermeldung ausgeben, wenn keine Parameter übergeben wurden. Und zwar über die stderr-Ausgabe.
-
lalas schrieb:
Du prüfst ob $# (Anzahl der Argumente) ungleich 0 ist. Warum läuft die Schleife nicht endlos bzw. wo ist die Abbruchbedingung ? Die Anzahl der übergebenen Argumente verändert sich doch nicht während die Schleife durchläuft...
Gibt in deiner Bash-shell
help shift
ein:shift: shift [n]
The positional parameters from $N+1 ... are renamed to $1 ... If N is
not given, it is assumed to be 1.shift 1
bewirkt, dass das erste Parameter$1
aus der Liste entfernt wird, d.h.$2
wird das neue$1
,$3
wird das neue$2
, usw. Das kann ich solange machen, bis keine Argumente mehr vorhanden sind. Dennshift 1
bleibt wirkungslos, wenn es keine Argumente mehr gibt. --> die schleife bricht bein
Durchläufe, wenn man [n]Parameter[/c] übergeben hat.lalas schrieb:
Ich will nämlich noch eine Fehlermeldung ausgeben, wenn keine Parameter übergeben wurden. Und zwar über die stderr-Ausgabe.
dann kannst du folgendes tun
#!/bin/sh if test $# -ne 0 ; then echo "`basename $0` needs at least one parameter" 1>&2 exit 1 fi
-
Hi,
okay danke für die Erklärung.
Hätte nicht gedacht das SHIFT auch $# beeinflusst. Die Ausgabe des Fehlers habe ich schon hinbekommen, danke aber auch dafür
Aber eine letzte Frage zum Rückgabewert bei error:
Gibt es da eine "Empfehlung" welchen Wert man bei Fehler zurückgeben soll ? In ANSI-C haben wir -1 zurückgegeben. Was sollte man bei Linux tun oder ist es mir komplett freigestellt ?
Gruss,
Lalas
-
Man gibt im Allgemeinen 0 bei Erfolg zurück und > 0 bei Fehlern. Auch in ANSI-C sollte man das machen, da UNIX-Shells das auch so interpretieren. Das kannst Du auch anhand der einfachen Shell-Hilfsprogramme sehen:
if test $# -ne 0; then
...heisst nichts anderes als "wenn das Programm
test $# -ne 0
0 zurückgibt, dann mache folgendes".Wenn Du also selbst ein test in ANSI-C implementieren wolltest, müsste das die main-Funktion bei Erfolg mit return 0 verlassen.
-
LordJaxom schrieb:
if test $# -ne 0; then
...heisst nichts anderes als "wenn das Programm
test $# -ne 0
0 zurückgibt, dann mache folgendes".okay, und hier mein denken:
"wenn $# UNGLEICH 0, dann mache ..."
Aber $# bleibt doch während das script durchläuft immer UNGLEICH 0. Wieso ist die Bedingung nicht mehr erfüllt wenn ich SHIFT ausführe ?
Die Anzahl der übergebenen Parameter verändert sich doch nicht..oder doch ?
-
lalas schrieb:
Aber $# bleibt doch während das script durchläuft immer UNGLEICH 0.
Wenn shift einen Parameter aus der Liste der Parameter entfernt, was passiert dann wohl mit der Anzahl der Parameter? Bleibt die gleich?
-
Das war ja eben mein Verständnisproblem;
Ich seh das so:
./befehl AAA BBB CCC
bdeutet für mich, dem 'befehl' werden 3 Parameter übergeben.
Nun wäre interessant was $# ganz offiziell bedeuten soll:
- Anzahl der übergebenen Parameter (die ändert sich meiner Meinung nach nie)
- Anzahl der Parameter in einer Art "Übergabeliste"Wenn also die Parameter in einer Art stack abgelegt werden oder in einem array oder sonstwas, wäre die Erklärung nachvollziehbar. Vielleicht kann hierzu jemand etwas sagen, "wie" werden denn die Parameter abgelegt ?
SHIFT bewirkt für mein Verständnis nur das verschieben dieser 3 Parameter in der Abarbeitung. Es bleibt aber bei 3 Parametern welche übergeben wurden.
Aber nun weiss ich ja, dass es anders gedacht ist
-
lalas schrieb:
Das war ja eben mein Verständnisproblem;
Ich seh das so:
./befehl AAA BBB CCC
bdeutet für mich, dem 'befehl' werden 3 Parameter übergeben.
$# heißt (wie tausendfach gesagt) Anzahl der übergebene Parameter. Das kannst du dir wie ein Stapel von Paremetern vorstellen. Wenn du ein Element aus dem Stapel löscht, dann hast du 'alte Größe' - 1 Elemente. MIt $# ist es genau dasselbe, denn du löscht mit
shift n
die ersten n Parametern. Das ist doch nicht so schwer zu verstehen, oder?
-
Ich weiss ja jetzt wie es gemeint ist
Kann also geschlossen werden...
Danke nochmals an alle
Gruss,
Lalas
-
wie wär's damit:
echo $* | tr ' ' "\n" | cat -n
-
in der Kürze liegt die Würze
-
Bin auch Anfänger im Bereich Shell-Scripts und erlaube es mir daher mal meine Frage hier zu posten.
Mein Ziel ist es, das wget mehrere Links gleichzeitig downloadet, die ich mittels sed aus der Datei auslese.
das sieht ca so aus:
#!/bin/bash i=1 max=3 #Anzahl der Downloads while [ $i -le $max ] do link=`sed -ne "$i p" "$1"` wget -c -b $link i=`expr $i + 1` done
Das erste Argument beim Aufruf ist der Name der Datei mit den Links.
Das Script befindet sich im Ornder /bin und hat als erste Zeile auch "#!/bin/bash" aber es funktioniert nicht wenn ich es aufrufe(kommt wget error "missing URL"), nur wenn ich es über sh aufrufe funzts.
Danke schonmal
EDIT: Ich weiß zwar nicht warum, aber wenn ich das Script umbenne läuft es auch wenn ich es ohne sh Aufrufe o.O