Zwracanie wartości z funkcji basha

Mam funkcję, która zwraca 1, jeśli liczba jest prawidłową dziesięciocyfrową liczbą:

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 } 

Jest wywoływany przez:

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

Funkcja działa poprawnie, jeśli numer jest prawidłowy, ale pokazuje składnię błąd, jeśli wprowadzisz nieprawidłową liczbę.

Odpowiedź

@choroba „Odpowiedź jest prawidłowa, jednak ten przykład może być bardziej zrozumiały:

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

Ten przykład jest nieco dłuższy (ustawienie $valNumResult, a następnie zapytanie o tę wartość), ale dokładniej opisuje, co się dzieje: valNum() zwraca wartość, którą można sprawdzić i przetestować.

PS Zrób sobie przysługę i zwróć 0 po true i niezerowe dla false. W ten sposób możesz użyć zwracanej wartości, aby wskazać „dlaczego nam się nie udało” w przypadku niepowodzenia.

Odpowiedź

Funkcje w bashu mogą zwracać tylko kody zakończenia. Zastępowanie poleceń, odwrotnie, jest używane do uzyskania standardowego wyjścia polecenie lub funkcja. Dlatego, aby sprawdzić zwróconą flagę, nie potrzebujesz podstawienia:

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

Ale żeby zadziałało, powinieneś zwrócić 0, jeśli numer jest ważny, i 1 jeśli nie jest (kod zakończenia 0 oznacza brak błędu).

Komentarze

  • Nie rozumiem. W przykładzie 24.7 w tldp.org/LDP/abs/html/complexfunct.html funkcja zwraca wartość maksymalną, a nie kod zakończenia. Chociaż twoja sugestia działa, ale nie jestem w stanie zrozumieć, dlaczego działa
  • , ponieważ twój test polega na sprawdzeniu, czy dane wejściowe są prawidłową 10-cyfrową liczbą całkowitą, czy nie, tj. Prawda czy fałsz, funkcja zwraca 0 lub 1. choroba ' Przykład działa, ponieważ if valnum "$num" jest równoważne z if valnum "$num" = 0 tj. ” jeśli to prawda „. podstawową zasadą w skryptach sh jest to, że 0 = prawda / sukces, wartość niezerowa = fałsz / błąd.
  • Przy okazji, ” Zaawansowany przewodnik po skryptach Bash ” to nie ' to bardzo dobry przewodnik – ' mylę się w wielu sprawach i zachęca do stosowania złych praktyk w zakresie pisania skryptów. Bash FAQ pod adresem mywiki.wooledge.org/BashFAQ jest znacznie lepszym źródłem.
  • patrz unix.stackexchange.com/questions/12236/ …
  • Twoja funkcja nie działa, ponieważ powtarza ciąg ” Nieprawidłowa liczba „, a następnie porównujesz numerycznie ten ciąg z liczbą 1 za pomocą if [[ $(valNum $num) -eq 1 ]]

Odpowiedź

Nie możesz zwrócić dowolnego wyniku z funkcji powłoki. Możesz zwrócić tylko kod stanu będący liczbą całkowitą z przedziału od 0 do 255. (Chociaż możesz przekazać większą wartość do return, jest ona obcięta modulo 256). Wartość musi wynosić 0 wskazać sukces i inną wartość wskazującą porażkę; zgodnie z konwencją powinieneś trzymać się kodów błędów od 1 do 125, ponieważ wyższe wartości mają specjalne znaczenie (złe polecenie zewnętrzne dla 126 i 127, zabite przez sygnał dla wyższych wartości).

Ponieważ zwracasz w tym przypadku wynik tak lub nie, kod statusu jest odpowiedni. Ponieważ flag wydaje się wskazywać na sukces lub porażkę, powinieneś użyć konwencjonalnych wartości 0 dla sukcesu i 1 dla porażki (przeciwieństwo tego, co napisałeś). Możesz wtedy użyć swojej funkcji bezpośrednio w instrukcji if.

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 

Jeśli chcesz rozróżnić kody błędów, wywołaj tę funkcję bezpośrednio. Natychmiast po zwróceniu kod błędu jest dostępny w $?. Następnie możesz to sprawdzić za pomocą instrukcji case:

valNum "$num" case $? in … 

Jeśli chcesz użyć kodu stanu później, zapisz go w innej zmiennej przed $? jest nadpisywane przez następne polecenie.

valNum "$num" valNum_status=$? 

To, co napisałeś, nie działa, ponieważ podstawianie poleceń $(…) rozwija się do wyniku funkcji, który w kodzie jest komunikatem o błędzie lub pustym, nigdy 1.

Jeśli potrzebujesz aby przekazać z funkcji powłoki więcej informacji niż pozwala na to kod statusu, istnieją dwie możliwości:

  • Wydrukuj jakiś tekst na standardowe wyjście i wywołaj funkcję w zamianie polecenia: $(valNum "$num")
  • Przypisz do jednej lub więcej zmiennych wewnątrz funkcji i przeczytaj te zmienne później.

Odpowiedź

Sam miałem sprzeczne wyniki w tym obszarze. Oto wyniki moich eksperymentów empirycznych.Po pierwsze, trochę „ teorii ” na temat poleceń bash lub * nix:

  • SUCCESS == 0 … a mianowicie. brak kodu stanu błędu)
  • FAIL              ! = 0 …… jakiś kod statusu

Przykład:

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

Wyjście:

ls: cannot access "/nonexistantdir": No such file or directory FAIL... ls: cannot access "/nonexistantdir": No such file or directory status = 2 

Jak pokazano, polecenie ls zwraca kod stanu = 2. Podczas próby prawidłowego katalogu stan wynosi zero ( 0 ). Nie to samo, co prawie we wszystkich innych językach.

reguła # 1 – Make …

  • TRUE   == 0
  • FALSE! = 0

Musimy pamiętać, że testujemy kody błędów w Bash if. Ustawiam stałe lub możesz użyć poleceń powłoki true lub false.

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 

i wyjście:

Invalid Number Not lucky. 

Jednak sugeruję podanie dowolnego „ głosuj w górę „@Gilles, ponieważ jego odpowiedź jest prawidłowa. Chciałem tylko przejrzeć uproszczenia w ePaper.

Jeszcze jedna rzecz, test . Wygląda to następująco:

[[ some-expression ]]; 

W większości przypadków. Na przykład:

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

Zero (0) jest true . Dlaczego? Cóż, strona podręcznika mówi, że pojedynczy argument jest „ prawdziwy ”, gdy NIE jest NULL.

odniesienia:

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *