Відповідно до посібника 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-гуру.