TL; DR: Trong trường hợp export FOO=bar
, bash gọi việc tạo môi trường tạm thời của nó, đặt FOO=bar
trong môi trường đó, sau đó đưa ra lệnh cuối cùng là export FOO
. Tại thời điểm đó, FOO
được coi là đối số cuối cùng.
Ah, bị lạm dụng nhiều $_
:
($ _, một dấu gạch dưới.) Khi khởi động shell, được đặt thành tên đường dẫn tuyệt đối được sử dụng để gọi shell hoặc shell script đang được thực thi như được truyền trong môi trường hoặc danh sách đối số. Sau đó, mở rộng đối số cuối cùng sang lệnh trước đó, sau khi mở rộng. Cũng được đặt thành tên đường dẫn đầy đủ được sử dụng để gọi từng lệnh được thực thi và được đặt trong môi trường được xuất sang lệnh đó. Khi kiểm tra thư, tham số này giữ tên của tệp thư.
Hãy xem xét một vài biến thể:
$ man; echo $_
What manual page do you want?
man
$ man foo; echo $_
No manual entry for foo
foo
$ echo; echo $_
echo
$ echo bar foo; echo $_
bar foo
foo
$ foo=x eval 'echo $foo'; echo $_
x
echo $foo
$ bar() { man $1; }; echo $_
foo
$ for (( i=0; $i<0; i=i+1 )); do echo $i; done; echo $_
foo
$ bar; echo $_
What manual page do you want?
man
$ bar foo; echo $_
No manual entry for foo
foo
$ MANPATH=/tmp; echo $_
$ export MANPATH=/tmp; echo $_
MANPATH
Vì vậy, chúng tôi thấy ba mẫu ở đây:
- Các lệnh được gọi từ hệ thống tập tin, các hàm và các hàm dựng sẵn hoạt động như thường thấy:
$_
được đặt thành tên lệnh nếu không có đối số, nếu không thì là đối số cuối cùng được trình bày.
- Sau khi định nghĩa hàm, các vòng lặp và các cấu trúc logic khác:
$_
không được sửa đổi.
- Mọi thứ khác:
$_
được đặt thành một cái gì đó không hoàn toàn mong đợi; kỳ dị.
Tôi đã sử dụng mã để cung cấp một số cái nhìn sâu sắc về sự kỳ lạ.
$ ./bash --noprofile --norc -c 'man foo'
lastword=[man]
lastarg=[foo]
$ ./bash --noprofile --norc -c 'export FOO=bar'
lastword=[export]
lastarg=[FOO=bar]
bind_variable, name=[FOO], value=[bar]
before bind_lastarg, lastarg=[FOO]
bind_lastarg, arg=[FOO]
bind_variable, name=[_], value=[FOO]
$ ./bash --noprofile --norc -c 'declare FOO=bar'
lastword=[declare]
lastarg=[FOO=bar]
bind_variable, name=[FOO], value=[(null)]
before bind_lastarg, lastarg=[FOO=bar]
bind_lastarg, arg=[FOO=bar]
bind_variable, name=[_], value=[FOO=bar]
Bạn có thể thấy rằng trình phân tích cú pháp nhìn thấy đối số cuối cùng dự kiến ( lastarg=
) trong mọi trường hợp, nhưng những gì xảy ra sau đó phụ thuộc vào những gì bash nghĩ sẽ xảy ra. Xem exec_cmd.c, exec_simple_command () .
Trong trường hợp export FOO=bar
, bash thực hiện chuyển nhượng và sau đó xuất biến. Điều này có vẻ phù hợp với khẳng định của tài liệu rằng đối số cuối cùng được tính sau khi mở rộng.
EDITOR
là một đối số để xuất