TL;DR :В случае export FOO=bar
bash вызывает создание временной среды, устанавливает FOO=bar
в этой среде, а затем выдает окончательную команду export FOO
. В этот момент FOO
принимается в качестве последнего аргумента.
Ах, много -оскорбленных$_
:
($_, an underscore.) At shell startup, set to the absolute pathname used to invoke the shell or shell script being executed as passed in the environment or argument list. Subsequently, expands to the last argument to the previous command, after expansion. Also set to the full pathname used to invoke each command executed and placed in the environment exported to that command. When checking mail, this parameter holds the name of the mail file.
Рассмотрим несколько вариантов:
$ man; echo $_
What manual page do you want?
man
$ man foo; echo $_
No manual entry for foo
foo
$ echo; echo $_
echo
$ echo bar foo; echo $_
bar foo
foo
$ foo=x eval 'echo $foo'; echo $_
x
echo $foo
$ bar() { man $1; }; echo $_
foo
$ for (( i=0; $i<0; i=i+1 )); do echo $i; done; echo $_
foo
$ bar; echo $_
What manual page do you want?
man
$ bar foo; echo $_
No manual entry for foo
foo
$ MANPATH=/tmp; echo $_
$ export MANPATH=/tmp; echo $_
MANPATH
Итак, мы видим здесь три модели:
$_
устанавливается на имя самой команды, если нет аргументов, в противном случае последний из представленных аргументов. $_
не изменяется. $_
настроено на что-то не совсем ожидаемое; странный. Я доработал код, чтобы пролить свет на странности.
$./bash --noprofile --norc -c 'man foo'
lastword=[man]
lastarg=[foo]
$./bash --noprofile --norc -c 'export FOO=bar'
lastword=[export]
lastarg=[FOO=bar]
bind_variable, name=[FOO], value=[bar]
before bind_lastarg, lastarg=[FOO]
bind_lastarg, arg=[FOO]
bind_variable, name=[_], value=[FOO]
$./bash --noprofile --norc -c 'declare FOO=bar'
lastword=[declare]
lastarg=[FOO=bar]
bind_variable, name=[FOO], value=[(null)]
before bind_lastarg, lastarg=[FOO=bar]
bind_lastarg, arg=[FOO=bar]
bind_variable, name=[_], value=[FOO=bar]
Вы можете видеть, что анализатор видит ожидаемый последний аргумент(lastarg=
)во всех случаях, но то, что происходит после этого, зависит от того, что, по мнению bash, должно произойти. См. выполнить _cmd.c,выполнить _простую _команду ().
В случае export FOO=bar
bash выполняет присваивание, а затем экспортирует переменную. Кажется, это согласуется с утверждением документации о том, что последний аргумент вычисляется после раскрытия.
curl https://example.com/script.sh | bash
Или sudo bash, если его нужно запустить от имени пользователя root.