Коли `_` змінна середовище bash shell?


10

Посібник Баша говорить (manpage, мій акцент):

Коли Bash викликає зовнішню команду, змінна $_встановлюється на повне ім'я команди та передається цій команді в її середовищі.

І ( Спеціальні параметри ):

_

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

  1. У баш-оболонці я запускаю:

    $ bash
    $ export | grep '_=' 

    Згідно з посібником, _повинна бути змінна середовища нової оболонки bash. exportповинен виводити всі змінні середовища нової оболонки bash, але він не виводить _. Тож мені цікаво, чи _змінна середовище нової оболонки bash?

  2. Насправді в будь-якій баш-корпусі відбувається те саме

    $ export | grep '_='

    нічого не виводить. Тож мені цікаво, чи _коли-небудь змінна середовище bash shell?

  3. Для порівняння:

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

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


1
Це змінна оболонка і передається в середовище команди ; його не обов'язково експортувати в середовище оболонки . exportє вбудованим, але якщо ви використовуєте printenv _, він покаже вам, як його викликали: /usr/bin/printenvу цій системі.
Toby Speight

Зверніть увагу , що bash -c export | grep _=(з Bash), буде показано , як батьківські оболонки застосують bashкоманду, навіть якщо $_вона НЕ задано в батьківському.
Toby Speight

Дивіться також 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 дозволяє виконувати завдання, без нарікань. Це просто не корисно, оскільки спеціальний ефект одразу перекриває значення.


2
Приємно, намагаючись використовувати _як змінну ;-). Це ефективно лише для запису, і значення втрачається негайно.
Стівен Кітт

1
Крім того, внутрішньо Bash трактує _як змінну, саме тому вона з'являється у висновку set. Однак, наскільки я можу визначити, це не можна позначити як експортований.
Стівен Кітт

2
@StephenKitt, але Bash 4.4 дозволяє позначити його лише для читання. Або ціле число. З дещо веселими результатами.
ilkkachu

1
Га, приємна знахідка, це досить кумедно!
Стівен Кітт

5

Не кожна змінна оболонка es позначена як експортована, як ви бачите на виході declare -p.

Це не має ніякого сенсу bash маркувати $_як експортований, оскільки він автоматично додає цю змінну до середовища дочірніх процесів, але з іншим значенням, ніж те, яке вона має в оболонці (на той момент).

Показ його як експортованого просто заплутає користувача щодо того, що буде з оточенням зовнішніх команд.

Усі "змінні періоду виконання" BASH*не експортуються.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.