Anfänger-Frage zur shell-Programmierung



  • 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: XXX

    echo $# 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. Denn shift 1 bleibt wirkungslos, wenn es keine Argumente mehr gibt. --> die schleife bricht bei n 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


Anmelden zum Antworten