Rückgabe eines Wertes aus einer Bash-Funktion

10

Ich habe eine Funktion, die 1 zurückgibt, wenn die Nummer eine gültige zehnstellige Nummer ist:

valNum()
{
    flag=1
    if [[ $1 != [1-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] ]]; then
        echo "Invalid Number"
        flag=0
    fi
    return $flag
}

Es wird aufgerufen von:

if [[ $(valNum $num) -eq 1 ]]; then
      #do something
fi

Die Funktion funktioniert einwandfrei, wenn die Nummer gültig ist, zeigt jedoch einen Syntaxfehler an, wenn eine ungültige Nummer eingegeben wird.

user2179293
quelle

Antworten:

14

Die Antwort von @ choroba ist korrekt, dieses Beispiel könnte jedoch klarer sein:

valNum $num
valNumResult=$? # '$?' is the return value of the previous command
if [[ $valNumResult -eq 1 ]]
then
  : # do something
fi

Dieses Beispiel ist etwas länger (Einstellung $valNumResultund Abfrage dieses Werts), beschreibt jedoch genauer, was passiert: Das valNum()gibt einen Wert zurück, und dieser Wert kann abgefragt und getestet werden.

PS Bitte tun Sie sich selbst einen Gefallen und kehren Sie 0für trueund ungleich Null zurück false. Auf diese Weise können Sie den Rückgabewert verwenden, um anzugeben, warum wir im Fehlerfall fehlgeschlagen sind.


quelle
8

Funktionen in Bash können nur Exit-Codes zurückgeben. Die Befehlssubstitution wird umgekehrt verwendet, um die Standardausgabe eines Befehls oder einer Funktion abzurufen. Um das zurückgegebene Flag zu überprüfen, benötigen Sie daher keine Ersetzung:

if valNum "$num" ; then
    # ...
fi

Damit dies funktioniert, sollten Sie 0 zurückgeben, wenn die Nummer gültig ist, und 1, wenn dies nicht der Fall ist (Exit-Code 0 bedeutet keinen Fehler).

Choroba
quelle
Ich verstehe es nicht. Im Beispiel 24.7 in tldp.org/LDP/abs/html/complexfunct.html gibt die Funktion den Maximalwert und nicht den Exit-Code zurück. Obwohl Ihr Vorschlag funktioniert, kann ich nicht verstehen, warum er funktioniert
user2179293
1
Da Ihr Test darin besteht, herauszufinden, ob die Eingabe eine gültige 10-stellige Ganzzahl ist oder nicht, dh wahr oder falsch, gibt die Funktion entweder 0 oder 1 zurück. Das Beispiel von choroba funktioniert, weil if valnum "$num"es äquivalent ist, if valnum "$num" = 0dh "wenn es wahr ist". Die Faustregel bei sh-Skripten lautet: 0 = wahr / Erfolg, ungleich Null = falsch / Fehler.
Cas
2
Übrigens, dieser "Advanced Bash-Scripting Guide" ist kein sehr guter Leitfaden - er ist in vielen Dingen falsch und fördert einige schlechte Skriptpraktiken. Die Bash-FAQ unter mywiki.wooledge.org/BashFAQ ist eine viel bessere Ressource.
Cas
Ihre Funktion schlägt fehl, weil sie die Zeichenfolge "Ungültige Nummer" wiedergibt und Sie dann einen numerischen Vergleich zwischen dieser Zeichenfolge und der Nummer 1 mitif [[ $(valNum $num) -eq 1 ]]
cas
5

Sie können kein beliebiges Ergebnis von einer Shell-Funktion zurückgeben. Sie können nur einen Statuscode zurückgeben, der eine Ganzzahl zwischen 0 und 255 ist. (Während Sie einen größeren Wert an übergeben können return, wird er modulo 256 abgeschnitten.) Der Wert muss 0 sein, um Erfolg anzuzeigen, und ein anderer Wert, um Fehler anzuzeigen. Konventionell sollten Sie sich an Fehlercodes zwischen 1 und 125 halten, da höhere Werte eine besondere Bedeutung haben (schlechter externer Befehl für 126 und 127, beendet durch ein Signal für höhere Werte).

Da Sie hier ein Ja-Nein-Ergebnis zurückgeben, ist ein Statuscode angemessen. Da dies flagauf einen Erfolg oder Misserfolg hinweist, sollten Sie die herkömmlichen Werte 0 für Erfolg und 1 für Misserfolg verwenden (das Gegenteil von dem, was Sie geschrieben haben). Sie können Ihre Funktion dann direkt in einer if-Anweisung verwenden.

valNum ()
{
  local flag=0
  if [[ $1 != [1-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] ]]; then
    echo 1>&2 "Invalid Number"
    flag=1
  fi
  return $flag
}
if valNum "$num"; then
  #do something
fi

Wenn Sie zwischen Fehlercodes unterscheiden müssen, rufen Sie die Funktion direkt auf. Unmittelbar nach der Rückkehr ist der Fehlercode in verfügbar $?. Sie können es dann mit einer case-Anweisung überprüfen:

valNum "$num"
case $? in 

Wenn Sie den Statuscode später verwenden müssen, speichern Sie ihn in einer anderen Variablen, bevor er $?vom nächsten Befehl überschrieben wird.

valNum "$num"
valNum_status=$?

Was Sie geschrieben haben, hat nicht funktioniert, da die Befehlsersetzung $(…)auf die Ausgabe der Funktion erweitert wird, die in Ihrem Code entweder die Fehlermeldung oder leer ist, niemals 1.

Wenn Sie mehr Informationen übergeben müssen, als ein Statuscode aus einer Shell-Funktion zulässt, haben Sie zwei Möglichkeiten:

  • Drucken Sie Text in der Standardausgabe und rufen Sie die Funktion in einer Befehlsersetzung auf: $(valNum "$num")
  • Weisen Sie einer oder mehreren Variablen innerhalb der Funktion zu und lesen Sie diese Variablen später.
Gilles 'SO - hör auf böse zu sein'
quelle
2

Ich habe selbst in diesem Bereich widersprüchliche Ergebnisse erzielt. Hier sind Ergebnisse meiner empirischen Experimente. Erstens eine ' Theorie ' über Bash- oder * nix-Befehle:

  • ERFOLG == 0 ... nämlich. kein Fehlerstatuscode)
  • FAIL! = 0 ...... ein Statuscode

Beispiel:

if  ls -lt /nonexistantdir
then 
    echo "found"
else
    echo "FAIL"
fi
#
echo
ls -lt /nonexistantdir; echo "status = $?"
echo "status = $?"

Ausgabe:

ls: cannot access '/nonexistantdir': No such file or directory
FAIL... 

ls: cannot access '/nonexistantdir': No such file or directory
status = 2

Wie gezeigt, gibt der lsBefehl den Statuscode = 2 zurück. Wenn Sie ein gültiges Verzeichnis versuchen, ist der Status Null ( 0 ). Nicht das gleiche wie fast alle anderen Sprachen.

Regel # 1 - Machen Sie ...

  • TRUE == 0
  • FALSE! = 0

Wir müssen uns daran erinnern, dass wir Fehlercodes in einer Bash- Anweisung testenif . Ich richte Konstanten ein, oder Sie können Shell trueoder falseBefehle verwenden.

TRUE=0
FALSE=1

#  valid number function
#
valNum()
{
    flag=$TRUE

    if [[ $1 != [1-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] ]]; then
        echo "Invalid Number"
        flag=$FALSE
    fi
    return $flag
}

#    later on ...
#
if validNum Abc 
then
    echo "Lucky number"
else
    echo "Not lucky."
fi

und Ausgabe:

Invalid Number
Not lucky.

Ich schlage jedoch vor, dass Sie @ Gilles eine " Up-Vote " geben, da seine Antwort die richtige ist. Ich wollte nur die vereinfachende Seite von ePaper auf den Punkt bringen.

Nur eine andere Sache, der testBefehl. Das sieht so aus:

[[ some-expression ]]; 

Meistens. Und zum Beispiel:

$ test 1
$ echo "result = $?"
result = 0
$ test 0
$ echo "result = $?"
result = 0

Null (0) ist wahr . Warum? Nun, die Manpage sagt, dass ein einzelnes Argument " wahr " ist, wenn es NICHT-NULL ist.

Verweise:

werden
quelle