TL; DR: У випадку export FOO=bar, коли bash посилається на своє тимчасове створення середовища, встановлює 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=) у всіх випадках, але те, що станеться далі, залежить від того, що баш думає, що має відбутися. Див. Execute_cmd.c, Execute_simple_command () .
У випадку з export FOO=barbash робить призначення, а потім експортує змінну. Це здається узгодженим із твердженням документації, що останній аргумент обчислюється після розширення.
EDITORє аргументом для експорту