function foo {
(cd $FOOBAR;
<some command>
if [$? -ne 0]
then
echo "Nope!"
else
echo "OK!"
fi
)
}
Próbuję napisać funkcję podobną do powyższej i umieścić ją w moim pliku .bashrc. Po źródle pliku i uruchomieniu otrzymuję:
Całkowity czas: 51 sekund
-bash: [1: polecenie nie znaleziono
OK!
Czy ktoś może mi pomóc zrozumieć, co zrobiłem źle?
$?
równa się 0 zif
instrukcją jest bezcelowe,if
oczekuje polecenia, a jeśli to polecenie powróci0
, uruchamia kod w bloku. więc przywróciif true; then echo hello; fi
echo, odkąd polecenietrue
powróciło0
.$?
przechowuje status ostatniego potoku , który nie jest poleceniemtest
([
) wif
instrukcji. Przykładem jest sprawdzenie, czy sięsome command
udało. Możesz zrobić to samo z&&
i||
, ale może to zrobić długie, nieczytelne linie w porównaniu doif [ $? -eq 0 ]
. Ten sam argument dotyczyif some command
$?
rozwija, wskazuję, że nie ma sensutest
być używanym; ponieważif some command
robi to samo z jedną instrukcją a dwiema osobnymi instrukcjami. jeśli polecenie jest już długie, dodanie trzech kolejnych znaków nie spowodowałoby, że „nieczytelne” byłoby znacznie bardziej „nieczytelne”.Odpowiedzi:
Dodaj spację po
[
, a drugą przed]
:[
jest wbudowane powłoki, to podobnie jak komendaecho
,read
,expr
... potrzebuje miejsca po nim, i wymaga dopasowania]
.Pisanie
[ $? -ne 0 ]
jest faktycznie wywoływanie[
i nadając jej 4 parametry:$?
,-ne
,0
, i]
.Uwaga: fakt, że pojawia się komunikat o błędzie
[1: command not found
oznacza, że$?
miał on wartość1
.źródło
[
jest link dotest
jak dobrze[
jest wbudowany w powłokę i/usr/bin/[
jest rzadko używany.Lub możesz
$?
całkowicie pominąć . Jeśli twoje polecenie brzmicmd
, powinny działać:źródło
Dobrą praktyką jest przypisanie wartości zwracanej do zmiennej przed jej użyciem
Pozwala ponownie wykorzystać wartość zwracaną. np. w instrukcji if ... elif ... else ...
źródło
[
(Bez spacji staje się to błędem składniowymbash
). Cofa się, jeśli edytujesz i naprawisz swój błąd.$?
bezpośrednio, ponieważ zepsuje się, jeśli kiedykolwiek, podczas późniejszej edycji skryptu, umieścisz linię między poleceniem a$?
czekiem.Jedynym powodem, dla którego chcesz użyć
$?
jako argumentów[
polecenia (niezależnie od tego, czy[
polecenie to jest uruchamiane w części warunkuif
instrukcji, czy nie) jest, gdy chcesz rozróżnić konkretny status zwrotu, na przykład:Składnia dla tych wszystkich
if
,while
,until
... sprawozdanie jestKtóry działa,
cmd-list2
jeślicmd-list1
się powiedzie lub wcmd-list3
inny sposób.[ "$?" -eq 0 ]
Komenda jest no-op. Ustawia$?
na 0, jeśli$?
wynosi 0, i$?
na niezerową, jeśli była niezerowa.Jeśli chcesz coś uruchomić, jeśli się
cmd
nie powiedzie, to:Ogólnie rzecz biorąc, nie musisz majstrować przy tym, nie
$?
mówiąc już o tym, która wartość oznaczatrue
lubfalse
. Jedynymi przypadkami są, jak powiedziałem powyżej, jeśli musisz rozróżnić określoną wartość lub jeśli musisz ją zachować na później (na przykład, aby zwrócić ją jako wartość zwracaną funkcji), na przykład:Pamiętaj również, że pozostawienie zmiennej niecytowanej to operator split + glob. Przywołanie tego operatora tutaj nie ma sensu, więc powinno być:
nie
, nie wspominając już o tym[ $? -ne 0 ]
(który wywołałby[$? -ne 0 ]
[
polecenie tylko wtedy, gdyby$IFS
zawierał pierwszy znak$?
).Zauważ też, że sposobem Bourne'a na zdefiniowanie funkcji jest trzymanie
function-name()
się polecenia. To miało miejsce w każdym Bourne shell wyjątkiem jakbash
iyash
(i nowszych wersjachposh
), które umożliwiają polecenia związek tylko (polecenia czym związek{...}
lub(...)
lub rzeczy jakfor...done
,if...fi
...function foo { ... }
toksh
składnia definicji funkcji. Nie ma powodu, dla którego chciałbyś go tutaj użyć.Kod można zapisać przenośnie (POSIXly):
Zauważ też, że
cd
bez-P
ma bardzo specjalne znaczenie (obsługuje ścieżki, które zawierają..
komponenty inaczej niż jakiekolwiek inne polecenie), więc lepiej jest włączyć je do skryptów, aby uniknąć nieporozumień.(ta funkcja zwraca,
false
jeślicd
zawiedzie, ale nie, jeśli<some command>
zawiedzie).źródło
Wierzę, że poniższe polecenie zrobi wszystko, co chcesz w jednym wierszu.
źródło