Zgodnie z instrukcją Bash zmienna środowiskowa BASH_COMMAND
zawiera
Komenda aktualnie wykonywana lub planowana do wykonania, chyba że powłoka wykonuje komendę w wyniku pułapki, w którym to przypadku jest to komenda wykonywana w chwili pułapki.
Pomijając tę narożną wielkość liter, jeśli dobrze rozumiem, oznacza to, że kiedy wykonuję polecenie, zmienna BASH_COMMAND
zawiera to polecenie. Nie jest absolutnie jasne, czy zmienna ta jest rozbrojona po wykonaniu polecenia (tj. Jest dostępna tylko podczas wykonywania polecenia, ale nie później), choć można argumentować, że ponieważ jest to „polecenie aktualnie wykonywane lub wkrótce wykonywane” , to nie polecenie zostało właśnie wykonane.
Ale sprawdźmy:
$ set | grep BASH_COMMAND=
$
Pusty. Spodziewałbym się zobaczyć, BASH_COMMAND='set | grep BASH_COMMAND='
a może po prostu BASH_COMMAND='set'
, ale pusty mnie zaskoczył.
Spróbujmy czegoś innego:
$ echo $BASH_COMMAND
echo $BASH_COMMAND
$
To ma sens. Wykonuję polecenie, echo $BASH_COMMAND
więc zmienna BASH_COMMAND
zawiera ciąg echo $BASH_COMMAND
. Dlaczego tym razem zadziałało, ale nie wcześniej?
Zróbmy to jeszcze set
raz:
$ set | grep BASH_COMMAND=
BASH_COMMAND='echo $BASH_COMMAND'
$
Więc poczekaj. To było ustawione, że kiedy wykonywane echo
polecenie, a on nie był wyłączony później. Ale kiedy wykonałem set
ponownie, BASH_COMMAND
nie został ustawiony na set
polecenie. Bez względu na to, jak często wykonuję set
polecenie tutaj, wynik pozostaje taki sam. Czy zmienna jest ustawiona podczas wykonywania echo
, ale nie podczas wykonywania set
? Zobaczmy.
$ echo Hello AskUbuntu
Hello AskUbuntu
$ set | grep BASH_COMMAND=
BASH_COMMAND='echo $BASH_COMMAND'
$
Co? Więc zmienna została ustawiona, kiedy wykonałem echo $BASH_COMMAND
, ale nie kiedy wykonałem echo Hello AskUbuntu
? Jaka jest teraz różnica? Czy zmienna jest ustawiona tylko wtedy, gdy bieżące polecenie faktycznie zmusza powłokę do oceny zmiennej? Spróbujmy czegoś innego. Może tym razem jakieś zewnętrzne polecenie, a nie wbudowane bash, dla odmiany.
$ /bin/echo $BASH_COMMAND
/bin/echo $BASH_COMMAND
$ set | grep BASH_COMMAND=
BASH_COMMAND='/bin/echo $BASH_COMMAND'
$
Hmm, ok ... znowu, zmienna została ustawiona. Czy moje obecne przypuszczenie jest prawidłowe? Czy zmienna jest ustawiana tylko wtedy, gdy należy ją ocenić? Czemu? Czemu? Z powodów wydajnościowych? Spróbujmy jeszcze raz. Spróbujemy grepować $BASH_COMMAND
w pliku, a ponieważ $BASH_COMMAND
powinien zawierać grep
polecenie, grep
powinien grep dla tego grep
polecenia (tj. Dla siebie). więc stwórzmy odpowiedni plik:
$ 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'
$
OK, ciekawe. Polecenie grep $BASH_COMMAND tmp
zostało rozszerzone do grep grep $BASH_COMMAND tmp tmp
(zmienna jest rozwinięta tylko raz, oczywiście), więc poszukałem grep
, raz w pliku, $BASH_COMMAND
który nie istnieje, i dwa razy w pliku tmp
.
P1: Czy moje obecne założenie jest prawidłowe, że:
BASH_COMMAND
jest ustawiany tylko wtedy, gdy polecenie próbuje to ocenić; i- to jest nie rozbroić po wykonaniu polecenia, choć opis może doprowadzić nas do przekonania, tak?
P2: Jeśli tak, dlaczego? Wydajność? Jeśli nie, jak inaczej można wyjaśnić zachowanie w powyższej sekwencji poleceń?
P3: Na koniec, czy jest jakiś scenariusz, w którym ta zmienna mogłaby być rzeczywiście użytecznie użyta? W rzeczywistości próbowałem użyć go w $PROMPT_COMMAND
celu przeanalizowania wykonywanego polecenia (i zrobić kilka rzeczy w zależności od tego), ale nie mogę, ponieważ jak tylko $PROMPT_COMMAND
wykonam wewnątrz siebie polecenie, aby spojrzeć na zmienną $BASH_COMMAND
, zmienną pobiera zestawy do tego polecenia. Nawet jeśli robię to MYVARIABLE=$BASH_COMMAND
na samym początku $PROMPT_COMMAND
, MYVARIABLE
zawiera ciąg MYVARIABLE=$BASH_COMMAND
, ponieważ przypisanie jest również poleceniem. (To pytanie nie dotyczy tego, w jaki sposób mogę uzyskać bieżące polecenie w ramach $PROMPT_COMMAND
wykonania. Wiem, że istnieją inne sposoby).
To trochę tak, jak w przypadku zasady nieoznaczoności Heisenberga. Po prostu obserwując zmienną, zmieniam ją.
bash
guru über-guru.