Когда `_` является переменной окружения оболочки bash?

10

Руководство Bash говорит (manpage, мой акцент):

Когда Bash вызывает внешнюю команду, для переменной $_задается полный путь к команде и она передается этой команде в своем окружении.

И ( специальные параметры ):

_

( $_подчеркивание.) При запуске оболочки задайте абсолютный путь, используемый для вызова оболочки или сценария оболочки, который выполняется, как передано в среде или списке аргументов. Затем расширяется до последнего аргумента предыдущей команды после расширения. Также задайте полный путь, используемый для вызова каждой команды, выполненной и помещенной в среду, экспортированную в эту команду. При проверке почты этот параметр содержит имя почтового файла.

  1. В оболочке bash я запускаю:

    $ bash
    $ export | grep '_=' 

    Согласно инструкции, _должна быть переменная окружения новой оболочки bash. exportдолжен выводить все переменные окружения новой оболочки bash, но не выводить _. Поэтому мне интересно, _является ли переменная окружения новой оболочки bash?

  2. На самом деле в любой оболочке bash происходит то же самое

    $ export | grep '_='

    ничего не выводит. Так что мне интересно, _является ли когда-нибудь переменная окружения оболочки bash?

  3. Для сравнения:

    $ dash
    $ export  | grep '_='        
    export _='/bin/dash'

Мой пост вдохновлен комментарием Майка и ответом Стефана .

Тим
источник
1
Это переменная оболочки, и она передается в командную среду; он не обязательно экспортируется в среду оболочки . exportявляется встроенным, но если вы используете printenv _, он покажет вам, как он был вызван: /usr/bin/printenvв этой системе.
Тоби Спейт
Обратите внимание , что bash -c export | grep _=(с Bash), будет показано , как родительские оболочки применят bashкоманду, даже если $_она не задано в родительском.
Тоби Спейт
См. Также unix.stackexchange.com/questions/293302 .
JdeBP

Ответы:

13

Да, _это переменная окружения новой оболочки Bash; Вы можете увидеть это, запустив

tr '\0' '\n' < /proc/$$/environ | grep _=

внутри оболочки: показывает содержимое начальной среды оболочки. Вы не увидите его в первой оболочке, потому что не было предыдущей оболочки, чтобы установить ее до ее запуска.

Расширение $_внутри Bash относится к _специальному параметру, который расширяется до последнего аргумента предыдущей команды. (Внутренне Bash обрабатывает это, используя _переменную оболочки, которая обновляется при каждом анализе команды, но на самом деле это деталь реализации. Она «не экспортируется» каждый раз, когда анализируется команда. ) exportНе отображается, _потому что это не так переменная, помеченная как экспортированная; однако вы можете увидеть это в выводе set.

В первом примере, новые разборы оболочки Bash и выполняют команды в своих стартовых файлах, поэтому при запуске explore | grep '-=', _уже переписаны и помечены как не экспортируются.

В этом dashпримере кажется, что он не выполняет ни одного загрузочного файла, поэтому вы видите переменную как переменную среды, которая была установлена ​​Bash перед запуском dash.

Стивен Китт
источник
Спасибо. В новой оболочке bash, почему ничего не export | grep '_='выводится? Почему в исходной оболочке bash ничего не tr '\0' '\n' < /proc/$$/environ | grep _=выводится?
Тим
9

exportбез аргументов перечисляет все экспортируемые переменные . _не является переменной, но указан в качестве специального параметра .

Несколько сбивает с толку, _также будет допустимым именем для переменной , в отличие от имен других специальных параметров. По крайней мере, Bash 4.4 позволяет назначений на него, без нареканий. Это просто бесполезно, потому что специальный эффект немедленно переопределяет значение.

ilkkachu
источник
2
Получайте удовольствие, пытаясь использовать _в качестве переменной, хотя ;-). Это эффективно только для записи, и значение немедленно теряется.
Стивен Китт
1
Кроме того, внутренне Bash воспринимается _как переменная, поэтому она отображается в выходных данных set. Однако он не может быть помечен как экспортированный, насколько я могу определить.
Стивен Китт
2
@StephenKitt, но Bash 4.4 позволяет отмечать его только для чтения. Или целое число. С несколько веселыми результатами.
ilkkachu
1
Ха, хорошая находка, это довольно забавно!
Стивен Китт
5

Не все переменные оболочки помечены как экспортированные, как вы можете видеть в выводе declare -p.

Не имеет смысла bashпомечать $_как экспортированные, потому что он автоматически добавляет эту переменную в среду дочерних процессов, но имеет значение, отличное от того, которое имеет в оболочке (на данный момент).

Отображение его как экспортированного просто запутает пользователя в том, что произойдет со средой внешних команд.

Все «переменные времени выполнения» BASH*не экспортируются.

Хауке Лагинг
источник