Согласно руководству по Bash , переменная окружения BASH_COMMANDсодержит
Команда, выполняемая в настоящее время или готовящаяся к исполнению, если только оболочка не выполняет команду в результате прерывания, и в этом случае это команда, выполняющаяся во время прерывания.
Если оставить в стороне этот случай с ловушкой, если я правильно понимаю, это означает, что когда я выполняю команду, переменная BASH_COMMANDсодержит эту команду. Не совсем ясно, является ли эта переменная неустановленной после выполнения команды (т. Е. Доступна ли она только во время выполнения команды, но не после), хотя можно утверждать, что, поскольку она является «командой , выполняемой в настоящее время или готовой к выполнению» , это не команда, которая была только что выполнена.
Но давайте проверим:
$ set | grep BASH_COMMAND=
$
Пустой. Я бы ожидал увидеть BASH_COMMAND='set | grep BASH_COMMAND='или, может быть, просто BASH_COMMAND='set', но пусто удивил меня.
Давайте попробуем что-то еще:
$ echo $BASH_COMMAND
echo $BASH_COMMAND
$
Ну, это имеет смысл. Я выполняю команду, echo $BASH_COMMANDи поэтому переменная BASH_COMMANDсодержит строку echo $BASH_COMMAND. Почему это сработало на этот раз, но не раньше?
Давайте сделаем setэто снова:
$ set | grep BASH_COMMAND=
BASH_COMMAND='echo $BASH_COMMAND'
$
Так что ждите. Он был установлен, когда я выполнил эту echoкоманду, и впоследствии он не был сброшен. Но когда я setснова выполнил , BASH_COMMAND не было установлено setкоманды. Независимо от того, как часто я выполняю setкоманду здесь, результат остается неизменным. Итак, установлена ли переменная при выполнении echo, но не при выполнении set? Посмотрим.
$ echo Hello AskUbuntu
Hello AskUbuntu
$ set | grep BASH_COMMAND=
BASH_COMMAND='echo $BASH_COMMAND'
$
Какая? Таким образом, переменная была установлена, когда я выполнял echo $BASH_COMMAND, но не когда я выполнял echo Hello AskUbuntu? Где разница сейчас? Переменная устанавливается только тогда, когда текущая команда сама заставляет оболочку вычислять переменную? Давайте попробуем что-то другое. Может быть, на этот раз какая-то внешняя команда, а не встроенная команда bash, для разнообразия.
$ /bin/echo $BASH_COMMAND
/bin/echo $BASH_COMMAND
$ set | grep BASH_COMMAND=
BASH_COMMAND='/bin/echo $BASH_COMMAND'
$
Хм, ладно ... опять переменная была установлена. Так верна ли моя нынешняя догадка? Переменная устанавливается только тогда, когда она должна быть оценена? Зачем? Зачем? По причинам производительности? Давайте сделаем еще одну попытку. Мы попытаемся выполнить поиск grep для $BASH_COMMANDфайла и, поскольку он $BASH_COMMANDдолжен содержать grepкоманду, grepдолжен выполнить grep для этой grepкоманды (т. Е. Для себя). Итак, давайте сделаем соответствующий файл:
$ echo -e "1 foo\n2 grep\n3 bar\n4 grep \$BASH_COMMAND tmp" > tmp
$ grep $BASH_COMMAND tmp
grep: $BASH_COMMAND: No such file or directory
tmp:2 grep <-- here, the word "grep" is RED
tmp:4 grep $BASH_COMMAND tmp <-- here, the word "grep" is RED
tmp:2 grep <-- here, the word "grep" is RED
tmp:4 grep $BASH_COMMAND tmp <-- here, the word "grep" is RED
$ set | grep BASH_COMMAND=
BASH_COMMAND='grep --color=auto $BASH_COMMAND tmp'
$
Ок, интересно. Команда grep $BASH_COMMAND tmpбыла расширена до grep grep $BASH_COMMAND tmp tmp(переменная раскрывается только один раз, конечно), и поэтому я нашел grep, один раз в файле, $BASH_COMMANDкоторый не существует, и два раза в файле tmp.
Q1: верно ли мое текущее предположение, что:
BASH_COMMANDустанавливается только тогда, когда команда пытается его реально оценить; а также- оно не сбрасывается после выполнения команды, хотя описание может заставить нас поверить в это?
Q2: если да, то почему? Спектакль? Если нет, как еще можно объяснить поведение в приведенной выше последовательности команд?
Q3: Наконец, есть ли сценарий, в котором эта переменная могла бы реально использоваться осмысленно? Я на самом деле пытался использовать его внутри $PROMPT_COMMANDдля анализа выполняемой команды (и делать что-то в зависимости от этого), но я не могу, потому что, как только внутри $PROMPT_COMMAND, я выполняю команду, чтобы посмотреть на переменную $BASH_COMMAND, переменную получает наборы для этой команды. Даже когда я делаю MYVARIABLE=$BASH_COMMANDпрямо в начале моего $PROMPT_COMMAND, тогда MYVARIABLEсодержит строку MYVARIABLE=$BASH_COMMAND, потому что назначение тоже команда. (Этот вопрос не о том, как я могу получить текущую команду в ходе $PROMPT_COMMANDвыполнения. Я знаю, что есть и другие способы.)
Это немного похоже на принцип неопределенности Гейзенберга. Просто наблюдая за переменной, я меняю ее.
bash-гуру.