Zobacz następujące przykłady i ich wyniki w powłokach POSIX:
false;echo $?
lubfalse || echo 1
:1
false;foo="bar";echo $?
lubfoo="bar" && echo 0
:0
foo=$(false);echo $?
lubfoo=$(false) || echo 1
:1
foo=$(true);echo $?
lubfoo=$(true) && echo 0
:0
Jak wspomniano w najczęściej głosowanej odpowiedzi na /programming/6834487/what-is-the-variable-in-shell-scripting :
$?
służy do znalezienia wartości zwracanej ostatnio wykonanej komendy.
Jest to prawdopodobnie nieco mylące w tym przypadku, więc pobierzmy definicję POSIX, która jest również cytowana w poście z tego wątku:
? Rozwija się do dziesiętnego statusu wyjścia ostatniego potoku (patrz Rurociągi).
Wygląda więc na to, że samo przypisanie liczy się jako polecenie (a raczej część potoku) o zerowej wartości wyjściowej, ale które ma zastosowanie przed prawą stroną przypisania (np. Wywołanie zamiany poleceń w moich przykładach tutaj).
Widzę, jak to zachowanie ma sens z praktycznego punktu widzenia, ale wydaje mi się dość niezwykłe, że samo zadanie liczyłoby się w tej kolejności. Być może, aby wyjaśnić, dlaczego jest to dla mnie dziwne, załóżmy, że zadanie było funkcją:
ASSIGNMENT( VARIABLE, VALUE )
wtedy foo="bar"
byłoby
ASSIGNMENT( "foo", "bar" )
i foo=$(false)
byłoby coś takiego
ASSIGNMENT( "foo", EXECUTE( "false" ) )
co oznaczałoby, że EXECUTE
uruchamia się jako pierwszy, a dopiero potem ASSIGNMENT
jest uruchamiany, ale nadal liczy się EXECUTE
status.
Czy mam rację w mojej ocenie, czy coś źle zrozumiałem / czegoś mi brakuje? Czy to są właściwe powody, dla których uważam to zachowanie za „dziwne”?
false;foo="bar";echo $?
zawsze zwraca 0, kiedy ostatnim prawdziwym poleceniem byłofalse
?” Zasadniczo przypisania zachowują się wyjątkowo, jeśli chodzi o kody wyjścia. Ich kod zakończenia ma zawsze wartość 0, z wyjątkiem sytuacji, gdy nie dzieje się tak z powodu działania elementu po prawej stronie zadania.Odpowiedzi:
Status wyjścia dla zadań jest dziwny . Najbardziej oczywistym sposobem niepowodzenia przypisania jest zaznaczenie zmiennej docelowej
readonly
.Zauważ, że nie podjęto ani prawdziwej, ani fałszywej ścieżki instrukcji if, niepowodzenie przypisania zatrzymało wykonanie całej instrukcji. bash w trybie POSIX, a ksh93 i zsh przerwie działanie skryptu, jeśli przypisanie nie powiedzie się.
Cytując tutaj standard POSIX :
Jest to dokładnie część zaangażowanej gramatyki powłoki
który pochodzi z
simple_command
(simple_command → cmd_prefix → ASSIGNMENT_WORD). Więc jeśli przypisanie się powiedzie, wówczas status wyjścia wynosi zero, chyba że nastąpiło zastąpienie polecenia, w którym to przypadku status wyjścia jest statusem ostatniego. Jeśli przypisanie nie powiedzie się, status wyjścia jest różny od zera, ale może nie być w stanie go złapać.źródło
Mówisz,
To nie jest okropny sposób patrzenia na to. Jest to jednak niewielkie uproszczenie. Ogólny status zwrotu z
to status wyjścia z . Zadanie, które występuje po przydział nie określa ogólny stan wyjścia na 0.cmd4
E=
D=
Ponadto, jak wskazuje Ikar , zmienne można ustawić jako tylko do odczytu. Rozważ następującą odmianę w przykładzie Iwana:
Mimo że
A
jest tylko do odczytu, bash wykonuje podstawienie polecenia po prawej stronieA=
- a następnie przerywa polecenie, ponieważA
jest tylko do odczytu. Jest to ponadto sprzeczne z twoją interpretacją, że wartość wyjściowa zadania ma zastosowanie przed prawą stroną zadania.źródło