Понять значение `$ _`

12

Не могли бы вы объяснить следующие предложения из руководства Bash $_, особенно о выделенных полужирным шрифтом частях, возможно, с некоторыми примерами?

  1. При запуске оболочки задайте абсолютный путь, используемый для вызова оболочки или сценария оболочки, который выполняется, как передано в среде или списке аргументов .

  2. Впоследствии расширяется до последнего аргумента предыдущей команды после расширения.

  3. Также задайте полный путь, используемый для вызова каждой команды, выполненной и помещенной в среду, экспортированную в эту команду .

  4. При проверке почты этот параметр содержит имя почтового файла.

Тим
источник
4
-1 вопрос неясен и не до конца изучен. Что вы пробовали? Где ваши ожидания не совпадают с текстом? Разве вы не понимаете слово «впоследствии»? Если бы новый пользователь задал этот же вопрос, у меня возникли бы те же вопросы (несмотря на мое схожее врожденное любопытство относительно того, как именно все работает).
Джефф Шаллер

Ответы:

20

Я согласен, это не очень понятно.

1. При запуске оболочки,

  • если _переменная была в среде, bashполученной , а затем bashостаются нетронутыми.

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

    bash-script some args

    Это bashбудет проходить _=/path/to/bash-scripв заданной среде bash-script, и именно это будет первоначальное значение $_ bashпеременной в bashоболочке, которая интерпретирует этот скрипт.

    $ env -i _=whatever bash -c 'echo "$_"'
    whatever
    
  • Теперь, если приложение ссылающееся не пропускает _переменное окружение , вызванная bashоболочка инициализируется $_в argv[0]получении себя , который может быть bash, или /path/to/bashили /path/to/some-scriptили что - нибудь еще (в приведенном выше примере, что будет , /bin/bashесли она-бах сценария был #! /bin/bash или в /path/to/bash-script зависимости от системы ).

    Таким образом, этот текст вводит в заблуждение, поскольку он описывает поведение вызывающей стороны, которая не bashимеет никакого контроля. Вызванное приложение bashможет очень хорошо не устанавливаться $_вообще (на практике, execlp()например, это делают только некоторые оболочки и несколько редких интерактивных приложений ), или оно может использовать его для чего-то совершенно другого (например, ksh93устанавливает его *pid*/path/to/command).

    $ env bash -c 'echo "$_"'
    /usr/bin/env   (env did not set it to /bin/bash, so the value we
                   get is the one passed to env by my interactive shell)
    $ ksh93 -c 'bash -c "echo \$_"'
    *20042*/bin/bash
    

2. Впоследствии

Впоследствии не очень понятно , либо. На практике это происходит, как только bashинтерпретируется простая команда в текущей среде оболочки.

  • В случае интерактивной оболочки это будет, например, первая простая команда, интерпретируемая из /etc/bash.bashrc.

    Например, по приглашению интерактивной оболочки:

     $ echo "$_"
     ]      (the last arg of the last command from my ~/.bashrc)
     $ f() { echo test; }
     $ echo "$_"
     ]      (the command-line before had no simple command, so we get
             the last argument of that previous echo commandline)
     $ (: test)
     $ echo "$_"
     ]      (simple command, but in a sub-shell environment)
     $ : test
     $ echo "$_"
     test
    
  • Для неинтерактивной оболочки это будет первая команда $BASH_ENVили код, переданный в эту оболочку, если $BASH_ENVона не установлена.

3. Когда Bash выполняет команду

Третий момент - это нечто иное, и намекается в обсуждении выше.

bashПодобно нескольким другим оболочкам, передаваемым _командам передается переменная окружения, содержащая путь, который bashиспользуется в качестве первого аргумента для execve()системных вызовов.

$ env | grep '^_'
_=/usr/bin/env

4. При проверке почты

Четвертый пункт описан более подробно в описании MAILPATHпеременной:

'MAILPATH'

Разделенный двоеточиями список имен файлов, который оболочка периодически проверяет на наличие новой почты .

Каждая запись в списке может указывать сообщение, которое печатается при поступлении новой почты в почтовый файл , отделяя имя файла от сообщения знаком «?». При использовании в тексте сообщения «$ _» расширяется до имени текущего почтового файла.

Пример:

$ MAILCHECK=1 MAILPATH='/tmp/a?New mail in <$_>' bash
bash$ echo test >> /tmp/a
New mail in </tmp/a>
Стефан Шазелас
источник
4

Попробуйте этот простой пример:

echo "$_"
echo "test"
echo "$_"

Запустите его, указав абсолютный путь ( /home/$USERNAME/test.sh); вывод:

/home/$USERNAME/test.sh
test
test

Первый $_содержит путь, который вы использовали для вызова скрипта, а второй - первый аргумент в середине echo. Для третьего элемента в списке, если вы запустите новый терминал и наберете echo, $_ он покажет переменную, PATHкоторая обычно используется для поиска и вызова команд (на моей машине с Ubuntu) в обычной оболочке или в абсолютном пути к вашему .bashrsфайлу в оболочка входа

Для четвертого пункта со страницы руководства bash:

При использовании в тексте сообщения $_расширяется до имени текущего почтового файла.

coffeMug
источник
Спасибо. (1) Вы можете объяснить третий случай с примерами? (2) Когда я открываю новую вкладку терминала gnome, вывод echo $_- EDITORи почему? В каком случае это следует? (3) Можете ли вы привести пример того, как проверять почту и как ее использовать $_в этом случае?
Тим
Откройте свой .bashrcи закомментируйте каждую строку там. Оставьте только одну строку, содержащую команду, похожую echo "test"или похожую. Сохранить и закрыть. Тогда беги bashи немедленно echo $_. Это последнее эхо должно напечатать тест на выходе.
coffeMug
Что касается почтовой части, я не использовал Unix mail и не установил рабочую почту в моей системе, поэтому не могу привести пример. Но должно быть очевидно, если вы будете следовать описанию MAILPATHв linuxcommand.org/lc3_man_pages/bash1.html
coffeMug
1
К сведению, каноническая, современная версия руководства по bash: gnu.org/software/bash/manual/bashref.html . Это версия 4.3, а страница linuxcommand была 4.1.
Джефф Шаллер
1

Для случая 2 пример стоит тысячи слов:

mkdir my_long_dir
cd $_

Делает то, что вы догадались / на что надеетесь. Дает мне простой заполнитель, когда я в командной строке, чтобы избавить меня от необходимости повторяться.

DSZ
источник