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
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:
if valnum "$num"
jest równoważne zif 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.if [[ $(valNum $num) -eq 1 ]]