Was macht „while test $# -gt 0“?

Was macht „while test $# -gt 0“?

Ich versuche, eine Funktion zu erstellen, und glaube, ich habe ein gut funktionierendes Beispiel gefunden, aber ich verstehe nicht die gesamte Logik dahinter.

Konkreter: Könnte mir jemand erklären, was Test in der „while“-Zeile ist und macht? Was ist $# (ist # nicht ein Kommentarzeichen?) und woher kommt der Parameter -gt 0? Ich konnte ihn auf der Manpage von „while“ nicht finden.

Hier ist das Beispiel:

function my_function()
{
while test $# -gt 0
do
    $
echo "$1"
    shift
done
}

Danke schön.

Antwort1

Während #es für sich allein genommen definitiv ein Kommentar ist, $#enthält es die Anzahl der an Ihre Funktion übergebenen Parameter.

testist ein Programm, mit dem Sie verschiedene Tests durchführen können, z. B. ob eine Zahl größer als eine andere Zahl ist (wenn Ihr Operator ist -gt; es gibt viele andere Operatoren, siehe man test). Es gibt Erfolg zurück, wenn der Test erfolgreich ist (in diesem Fall, wenn the number of parametersgrößer als 0 ist).

Der shiftBefehl wirft den ersten Parameter weg. Außerdem verringert er$#

Der Code als Ganzes kann wie folgt betrachtet werden: Machen Sie etwas mit einem Parameter (in diesem Fall, indem Sie ihn auf dem Bildschirm anzeigen), verwerfen Sie ihn dann und wiederholen Sie dies, bis keine Parameter mehr übrig sind.

Wenn Sie alle verbleibenden Parameter sehen möchten, die für das Debuggen nützlich sind, überprüfen Sie den Inhalt von$@

Antwort2

$#==> Skriptparameter übergeben

test==> Befehl zur Bedingungsauswertung

-gt==> steht fürgrößer als

test a -gt b==> wahr, wenn a größer als b ist, andernfalls falsch

Alles zusammen:

while test $# -gt 0==> während mehr Parameter übergeben werden (der Grund für die Änderung ist die Verschiebung)

Was die Sache knifflig macht, liegt shiftim Hauptteil der While-Schleife.

$1==> stellt immer den ersten Parameter dar

Um dies konkreter zu machen, nehmen wir an, Sie übergeben die Parameter aund .bc

$1==> stellt dar a, dass dies Ihr erster Parameter ist

durch den Aufruf von jetzt shiftist aweg und Ihre Parameterliste ist jetzt bund cdaher $1ist es, wenn Sie jetzt aufrufen b, da dies jetzt der erste Parameter in der Liste ist. Wenn Sie shiftnoch einmal aufrufen, ist Ihre Parameterliste jetzt nur c, daher $1ist jetzt c. shiftEin weiterer Aufruf lässt die Parameterliste leer, daher wird die while-Bedingung nicht erfüllt (da die Parameterliste nicht mehr größer als 0 ist, da sie jetzt die Größe Null hat), was dazu führt, dass die while-Schleife beendet wird.

Welche Vorteile bietet die Verwendung shiftund Bezugnahme auf den aktuellen Parameter als $1?

Es gibt Ihnen die Flexibilität, in Ihrem Skript nicht im Voraus zu wissen, wie viele Parameter im Skript übergeben werden, und diese trotzdem einzeln zu durchlaufen, wobei Sie innerhalb der while-Schleife immer auf den aktuellen Parameter verweisen, da $1dies den Kopf der Parameterliste bedeutet. Durch shifting wird die Parameterliste schließlich leer sein, daher ist es wichtig, die while-Bedingung zu haben, um zu prüfen, ob sie größer als Null ist, um zu beenden und nicht in eine Endlosschleife zu geraten.

Antwort3

Führen Sie das folgende Skript aus, um zu verstehen, was die Variablen bedeuten. Speichern Sie das Skript unter somescript.shund rufen Sie es mit einigen Eingabeparametern auf.

#!/bin/bash
echo "I display the total parameters passed to this script from commandline"
echo $#
echo "I display all the parameter values"
echo "Input: $@"
echo "I display the first parameter value"
echo "$1"

shift 
echo "After shift: $@"

Antwort4

Wenn Sie mir verzeihen, dass ich die Antworten etwas wiederverwende, ich denke, Sie könnten dies nützlich finden.

_fn() { set -- "$@" $(cat)
    while ${1+:} false ; do 
        echo "$1" && [ "$1" = "arg2" ] && echo "$1"
        $YOUR_CHK
        shift
    done
}

echo "arg2" | _fn "arg1"

AUSGABE

arg1
arg2
arg2

Dies verarbeitet sowohl Befehlszeilenargumente als auch stdin. Es führt die whileSchleife nur aus, um sie zu überprüfen, während Sie noch mindestens ein Argument in Ihrem Parameterarray gespeichert haben. Es verwirft jedes überprüfte Argument, daher $YOUR_CHKsollte ein Teil davon das Speichern von Informationen sein, die Sie auf die eine oder andere Weise für wertvoll halten.

_fnwürde sich genauso verhalten, wenn sein Inhalt der Hauptteil eines Skripts wäre oder in der Form einer Shell-Funktion vorliegen würde.

_fnGriffe stdin- in diesem Fall "arg2" echoed über die |pipe- in der ersten Zeile durch setting seines Positionsparameter-Shell- $@Arrays auf alles, was auf der Kommandozeile übergeben wird - oder "$@"- UND alles catwird über ausgespuckt $(comand substitution).

while _fn's $1Der erste Parameter ist, dass ${set+}wir das eingebaute Shell-Element ersetzen, :trueum die whileSchleifenbedingung zu erfüllen. Sobald $1nicht gesetzt ist, dass die Ersetzung fehlschlägt, wird die Bedingung ausgewertet falseund die whileSchleife wird abgebrochen.

Für jede Iteration der whileSchleife _fn() echowird der $1erste Parameter &&bei Erfolg ( echoiststetserfolgreich), [ tests ]um zu sehen, ob es $1der Zeichenfolge entspricht "arg2" &&, wenn es erneut [ test ]erfolgreich ist ._fn() echo$1

$YOUR_CHKist ein Null-Op – es handelt sich um eine nicht gesetzte Variable, die nichts ergibt, bevor die Shell überhaupt Code ausführt.

Bei jeder Iteration der whileSchleife shiftentfernen wir den $1ersten Parameter. Bei Iteration 1 "$@"sieht das also so aus:

arg1 arg2

Aber nach shiftdem ersten Mal sieht es so aus:

arg2

Und nachdem wir shiftdas letzte Mal dabei waren, sieht es so aus:

Damit kommen wir wieder zurück zu ${1+:} false- da $1nun nicht mehr gesetzt ist, wird die Shell nicht ersetzen :trueund stattdessen nur falseausgewertet, was die whileSchleife unterbricht und die_fn().

verwandte Informationen