Podstawową ideą jest to, że VAR=VALUE some-command
ustawia VAR
się VALUE
na wykonanie some-command
kiedy some-command
jest zewnętrznym poleceniem i nie robi się to bardziej wymyślne. Jeśli połączysz tę intuicję z pewną wiedzą na temat działania powłoki, w większości przypadków powinieneś znaleźć właściwą odpowiedź. Odniesieniem do POSIX są „Proste polecenia” w rozdziale „Język poleceń powłoki” .
Jeśli some-command
jest poleceniem zewnętrznym , VAR=VALUE some-command
jest równoważne z env VAR=VALUE some-command
. VAR
jest eksportowany w środowisku some-command
, a jego wartość (lub brak wartości) w powłoce się nie zmienia.
Jeśli some-command
jest funkcją , to VAR=VALUE some-command
jest równoważne VAR=VALUE; some-command
, tj . Przypisanie pozostaje na miejscu po powrocie funkcji, a zmienna nie jest eksportowana do środowiska. Powodem tego jest konstrukcja powłoki Bourne'a (a następnie zgodność wsteczna): nie miała możliwości zapisywania i przywracania wartości zmiennych wokół wykonywania funkcji. Brak eksportowania zmiennej ma sens, ponieważ funkcja jest wykonywana w samej powłoce. Jednak ksh (w tym zarówno ATT ksh93, jak i pdksh / mksh), bash i zsh implementują bardziej użyteczne zachowanie, które VAR
jest ustawiane tylko podczas wykonywania funkcji (jest również eksportowane). W ksh odbywa się to, jeśli funkcja jest zdefiniowana za pomocą składni kshfunction NAME …
, nie jeśli jest zdefiniowany ze standardową składnią NAME ()
. W bash odbywa się to tylko w trybie bash, a nie w trybie POSIX (po uruchomieniu z POSIXLY_CORRECT=1
). W zsh odbywa się to, jeśli posix_builtins
opcja nie jest ustawiona; ta opcja nie jest ustawiona domyślnie, ale jest włączona przez emulate sh
lub emulate ksh
.
Jeśli some-command
jest wbudowane, zachowanie zależy od typu wbudowanego. Specjalne wbudowane zachowują się jak funkcje. Specjalne wbudowane to te, które muszą zostać zaimplementowane w powłoce, ponieważ wpływają na powłokę stanu (np. Wpływają na break
przepływ sterowania, cd
wpływają na bieżący katalog, set
wpływają na parametry pozycyjne i opcje…). Inne wbudowane funkcje są wbudowane tylko dla wydajności i wygody (głównie - np. Funkcja bash printf -v
może być zaimplementowana tylko przez wbudowane) i zachowują się jak polecenie zewnętrzne.
Przypisanie odbywa się po rozwinięciu aliasu, więc jeśli some-command
jest to alias , rozwiń go najpierw, aby znaleźć, co się stanie.
Zauważ, że we wszystkich przypadkach przypisanie jest wykonywane po przeanalizowaniu wiersza poleceń, w tym wszelkich podstawień zmiennych w samym wierszu poleceń. Tak var=a; var=b echo $var
drukuje a
, ponieważ $var
jest oceniane przed przypisaniem. I w ten sposób IFS=. printf "%s\n" $var
używa starej IFS
wartości do podziału $var
.
Omówiłem wszystkie typy poleceń, ale jest jeszcze jeden przypadek: gdy nie ma polecenia do wykonania , tj. Jeśli polecenie składa się tylko z przypisań (i ewentualnie przekierowań). W takim przypadku przypisanie pozostaje na miejscu . VAR=VALUE OTHERVAR=OTHERVALUE
jest równoważne z VAR=VALUE; OTHERVAR=OTHERVALUE
. Więc po IFS=. arr=($var)
, IFS
pozostaje ustawiony na .
. Ponieważ można użyć $IFS
w przypisaniu arr
z oczekiwaniem, że ma już swoją nową wartość, sensowne jest, aby nowa wartość parametru IFS
była używana do rozszerzenia $var
.
Podsumowując, możesz użyć tylko IFS
do tymczasowego podziału pola:
- uruchamiając nową powłokę lub podpowłokę (np.
third=$(IFS=.; set -f; set -- $var; echo "$3")
jest to skomplikowany sposób, z third=${var#*.*.}
wyjątkiem tego, że zachowują się inaczej, gdy wartość parametru var
zawiera mniej niż dwa .
znaki);
- w ksh,
IFS=. some-function
gdzie gdzie some-function
jest zdefiniowane za pomocą składni ksh function some-function …
;
- w bash i zsh, o
IFS=. some-function
ile działają one w trybie macierzystym, a nie w trybie zgodności.
IFS
pozostaje ustawiony na.
” Eek. Po przeczytaniu pierwszej części ma to sens, ale zanim opublikowałem to pytanie, nie spodziewałbym się tego.