Theo hướng dẫn Bash , biến môi trường BASH_COMMAND
chứa
Lệnh hiện đang được thực thi hoặc sắp được thực thi, trừ khi shell đang thực thi lệnh là kết quả của một cái bẫy, trong trường hợp đó là lệnh thực thi tại thời điểm bẫy.
Đặt trường hợp góc bẫy đó sang một bên, nếu tôi hiểu chính xác điều này có nghĩa là khi tôi thực thi một lệnh, biến BASH_COMMAND
chứa lệnh đó. Không hoàn toàn rõ ràng liệu biến đó có bị hủy sau khi thực thi lệnh hay không (nghĩa là chỉ có sẵn trong khi lệnh đang chạy, nhưng không phải sau đó), mặc dù người ta có thể lập luận rằng đó là "lệnh hiện đang được thực thi hoặc sắp được thực thi" , nó không phải là lệnh vừa được thực thi.
Nhưng hãy kiểm tra:
$ set | grep BASH_COMMAND=
$
Trống. Tôi đã dự kiến sẽ thấy BASH_COMMAND='set | grep BASH_COMMAND='
hoặc có thể chỉ BASH_COMMAND='set'
, nhưng trống rỗng làm tôi ngạc nhiên.
Hãy thử một cái gì đó khác:
$ echo $BASH_COMMAND
echo $BASH_COMMAND
$
Vâng, điều đó có ý nghĩa. Tôi thực hiện lệnh echo $BASH_COMMAND
và vì vậy biến BASH_COMMAND
chứa chuỗi echo $BASH_COMMAND
. Tại sao nó làm việc lần này, nhưng không phải trước đây?
Chúng ta hãy làm set
lại:
$ set | grep BASH_COMMAND=
BASH_COMMAND='echo $BASH_COMMAND'
$
Vậy còn chờ gì nữa. Nó được thiết lập khi tôi thực hiện echo
lệnh đó và sau đó nó không được đặt. Nhưng khi tôi thực hiện set
lại, BASH_COMMAND
không được đặt thành set
lệnh. Cho dù tôi có thường xuyên thực hiện set
lệnh ở đây không, kết quả vẫn như cũ. Vì vậy, là biến được đặt khi thực hiện echo
, nhưng không phải khi thực hiện set
? Hãy xem nào.
$ echo Hello AskUbuntu
Hello AskUbuntu
$ set | grep BASH_COMMAND=
BASH_COMMAND='echo $BASH_COMMAND'
$
Gì? Vì vậy, biến được đặt khi tôi thực thi echo $BASH_COMMAND
, nhưng không phải khi tôi thực hiện echo Hello AskUbuntu
? Sự khác biệt bây giờ ở đâu? Là biến chỉ được đặt khi lệnh hiện tại thực sự buộc shell để đánh giá biến? Hãy thử một cái gì đó khác nhau. Có thể một số lệnh bên ngoài lần này, không phải là một bash dựng sẵn, cho một sự thay đổi.
$ /bin/echo $BASH_COMMAND
/bin/echo $BASH_COMMAND
$ set | grep BASH_COMMAND=
BASH_COMMAND='/bin/echo $BASH_COMMAND'
$
Hmm, ok ... một lần nữa, biến đã được đặt. Vậy dự đoán hiện tại của tôi có đúng không? Là biến chỉ được đặt khi nó phải được đánh giá? Tại sao? Tại sao? Vì lý do hiệu suất? Hãy thử thêm một lần nữa. Chúng tôi sẽ cố gắng grep cho $BASH_COMMAND
trong một tệp và $BASH_COMMAND
sau đó sẽ chứa một grep
lệnh, grep
nên grep cho grep
lệnh đó (nghĩa là cho chính nó). vì vậy hãy tạo một tệp thích hợp:
$ 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, thú vị. Lệnh grep $BASH_COMMAND tmp
đã được mở rộng thành grep grep $BASH_COMMAND tmp tmp
(biến được mở rộng chỉ một lần, dĩ nhiên), và vì vậy tôi đã tham gia grep
, một lần trong một tệp $BASH_COMMAND
không tồn tại và hai lần trong tệp tmp
.
Q1: Giả định hiện tại của tôi có đúng không:
BASH_COMMAND
chỉ được đặt khi một lệnh cố gắng thực sự đánh giá nó; và- Nó không được đặt sau khi thực hiện một lệnh, mặc dù mô tả có thể khiến chúng ta tin như vậy?
Q2: Nếu có, tại sao? Hiệu suất? Nếu không, làm thế nào khác hành vi trong chuỗi lệnh trên có thể được giải thích?
Câu 3: Cuối cùng, có kịch bản nào trong đó biến này thực sự có thể được sử dụng một cách có ý nghĩa không? Tôi thực sự đã cố gắng sử dụng nó bên trong $PROMPT_COMMAND
để phân tích lệnh đang được thực thi (và thực hiện một số thứ tùy thuộc vào điều đó), nhưng tôi không thể, vì ngay khi, trong tôi $PROMPT_COMMAND
, tôi thực hiện một lệnh để xem biến $BASH_COMMAND
, biến được thiết lập để lệnh đó. Ngay cả khi tôi thực hiện MYVARIABLE=$BASH_COMMAND
ngay từ đầu $PROMPT_COMMAND
, sau đó MYVARIABLE
chứa chuỗi MYVARIABLE=$BASH_COMMAND
, bởi vì một phép gán cũng là một lệnh. (Câu hỏi này không phải là về cách tôi có thể nhận được lệnh hiện tại trong khi $PROMPT_COMMAND
thực thi. Có nhiều cách khác, tôi biết.)
Nó hơi giống với nguyên tắc bất định của Heisenberg. Chỉ bằng cách quan sát biến, tôi thay đổi nó.
bash
über-gurus thực sự ở đó.