Відповідно до посібника 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
? Де зараз різниця? Чи встановлена змінна лише тоді, коли сама поточна команда фактично змушує оболонку оцінювати змінну? Спробуємо щось інше. Можливо, якась зовнішня команда цього разу не зміна башти.
$ /bin/echo $BASH_COMMAND
/bin/echo $BASH_COMMAND
$ set | grep BASH_COMMAND=
BASH_COMMAND='/bin/echo $BASH_COMMAND'
$
Хм, добре ... знову ж, змінна була встановлена. То чи правильна моя теперішня здогадка? Чи встановлюється змінна лише тоді, коли її потрібно оцінювати? Чому? Чому? З міркувань продуктивності? Зробимо ще одну спробу. Ми постараємося $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
-гуру.