TL; DR: В случае export FOO=barbash вызывает создание своего временного окружения, устанавливает его FOO=barв этом окружении, а затем выдает окончательную команду export FOO. В этот момент FOOпринимается за последний аргумент.
Ах, много-злоупотребляли $_:
($ _, подчеркивание.) При запуске оболочки задайте абсолютный путь, используемый для вызова оболочки или сценария оболочки, выполняемого в том виде, как он был передан в среде или списке аргументов. Затем расширяется до последнего аргумента предыдущей команды после расширения. Также задайте полный путь, используемый для вызова каждой команды, выполненной и помещенной в среду, экспортированную в эту команду. При проверке почты этот параметр содержит имя почтового файла.
Давайте посмотрим на несколько вариантов:
$ 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. Смотрите execute_cmd.c, execute_simple_command () .
В случае export FOO=barbash выполняет присваивание, а затем экспортирует переменную. Это похоже на утверждение документации о том, что последний аргумент вычисляется после расширения.
EDITORаргумент для экспорта