$_
jest uważany za ostatni argument poprzedniego polecenia.
Zastanawiam się więc, dlaczego tak nie jest, EDITOR="emacs -nw"
ale EDITOR
w poniższym przykładzie?
Dlaczego nie jest "emacs -nw"
częścią ostatniego argumentu?
Mówiąc bardziej ogólnie, jakie są definicje argumentu i ostatni argument?
Dzięki.
$ export EDITOR="emacs -nw"
$ echo $_
EDITOR
EDITOR
jest argumentem do eksportupdksh
idash
będzie zawierać przypisaną wartość, aleksh93
będzie się zachowywał tak, jakbash
robi.export FOO=bar; echo $_
drukujeexport
.export
jest wbudowanym narzędziem.typeset -x FOO=bar
następnieecho $_
drukujeFOO
, ale wdeclare -x FOO=bar; echo $_
drukach BashFOO=bar
.Odpowiedzi:
Bash przetwarza zmienne zadania, gdy są one dopuszczone jako argumenty (z
alias
,declare
,export
,local
,readonly
, itypeset
), zanim cokolwiek innego (albo raczej, identyfikuje je, zanim cokolwiek innego - rozbudowa dotyczy wartości przypisanych do zmiennych). Kiedy dochodzi do rozwinięcia słowa, pozostałe polecenie jestexport EDITOR
, więc_
jest ustawione naEDITOR
.Ogólnie rzecz biorąc, argumentami są „słowa” pozostałe po rozwinięciu (które nie obejmują przypisań zmiennych i przekierowań).
Aby uzyskać szczegółowe informacje, zobacz Proste rozszerzanie poleceń w podręczniku Bash.
źródło
declare
, że zachowanie nie pasuje do tego, co opisuję ...declare a=b; echo $_
odciskia=b
;export c=d; echo $_
drukuje tylkoc
.alias
wydaje się wypisywać tylko nazwę,local
z drugiej strony wypisuje cały argument. Areadonly
także drukuje tylko nazwę, co było dla mnie trochę zaskakujące, ponieważ myślałamreadonly
ilocal
byłaby podobna dodeclare
.export
ireadonly
są zadeklarowane razem wsetattr.def
,declare
,local
, itypeset
są zadeklarowanedeclare.def
,alias
stoi samotniealias.def
.alias, declare, export, local, readonly
itypeset
. Co się stało pierwsze i następne? „Kiedy dochodzi do rozwinięcia słowa, pozostałe polecenie toexport EDITOR
”, czy sugerujesz, że przypisanie zmiennychEDITOR="emacs -nw"
następuje przed rozwinięciem? Jeśli nie, dlaczego pozostałe polecenie nie zawiera przypisania jako argumentu? Jeśli tak, to czy rozszerzenie wartości przypisanych zmiennym nie musi nastąpić przed wykonaniem przypisania zmiennej?TL; DR: W przypadku
export FOO=bar
bash wywołuje tymczasowe tworzenie środowiska, ustawia sięFOO=bar
w tym środowisku, a następnie wydaje polecenie końcoweexport FOO
. W tym momencieFOO
jest uważany za ostatni argument.Ach, nadużywane
$_
:Spójrzmy na kilka odmian:
Widzimy tutaj trzy wzory:
$_
w przypadku braku argumentów ustawiana jest sama nazwa polecenia, w przeciwnym razie ostatni z przedstawionych argumentów.$_
nie jest modyfikowany.$_
jest ustawione na coś, czego nie do końca się spodziewam; dziwne.Oprzyrządowałem kod, aby zapewnić wgląd w dziwność.
Możesz zobaczyć, że parser widzi oczekiwany ostatni argument (
lastarg=
) we wszystkich przypadkach, ale to, co stanie się później, zależy od tego, co według bash powinno się wydarzyć. Zobacz execute_cmd.c, execute_simple_command () .W przypadku
export FOO=bar
bash dokonuje przypisania, a następnie eksportuje zmienną. Wydaje się to spójne z twierdzeniem dokumentacji, że ostatni argument został obliczony po rozwinięciu.źródło
MAILCHECK
Aby odpowiedzieć na pytanie tytułowe, spróbuj
!$
:To jest ekspansja historii. Z strony podręcznika bash:
...
...
...
...
...
...
źródło
export EDITOR="emacs -nw"
» składa się z dwóch słów: pierwsze to «export
», a drugie «EDITOR="emacs -nw"
». Pytanie naprawdę brzmi: „Co oznacza strona podręcznika bash i Podręcznik Bash, gdy mówią, że!_
„ rozwija się do ostatniego argumentu do poprzedniego polecenia ”, biorąc pod uwagę, że w tym przypadku bash ustawia się$_
na«EDITOR
»?” Kopiowanie i wklejanie sekcji strony podręcznika bash na temat rozszerzania historii nie jest szczególnie pomocne.