TL; DR: Dalam kasus export FOO=bar, bash memanggil penciptaan lingkungan sementara, menetapkan FOO=bardalam lingkungan itu, lalu menghasilkan perintah terakhir dari export FOO. Pada titik itu, FOOdiambil sebagai argumen terakhir.
Ah, yang paling banyak disalahgunakan $_:
($ _, sebuah garis bawah.) Pada startup shell, setel ke pathname absolut yang digunakan untuk memanggil shell atau skrip shell yang dieksekusi sebagaimana diteruskan dalam daftar lingkungan atau argumen. Selanjutnya, perluas argumen terakhir ke perintah sebelumnya, setelah ekspansi. Juga setel ke nama path lengkap yang digunakan untuk memanggil setiap perintah yang dieksekusi dan ditempatkan di lingkungan yang diekspor ke perintah itu. Saat memeriksa email, parameter ini menyimpan nama file email.
Mari kita lihat beberapa variasi:
$ 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
Jadi kita melihat tiga pola di sini:
- Perintah yang dipanggil dari filesystem, fungsi, dan built-in berperilaku seperti yang diharapkan secara umum:
$_diatur ke nama perintah itu sendiri jika tidak ada argumen, kalau tidak argumen terakhir yang disajikan.
- Setelah definisi fungsi, loop, dan konstruksi logis lainnya:
$_tidak diubah.
- Yang lainnya:
$_diatur ke sesuatu yang tidak terlalu diharapkan; aneh.
Saya telah memasukkan kode untuk memberikan wawasan tentang keanehan.
$ ./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]
Anda dapat melihat bahwa parser melihat argumen terakhir yang diharapkan ( lastarg=) dalam semua kasus, tetapi apa yang terjadi setelahnya tergantung pada apa yang menurut bash harus terjadi. Lihat execute_cmd.c, execute_simple_command () .
Dalam kasus export FOO=bar, bash membuat tugas dan kemudian mengekspor variabel. Ini tampaknya konsisten dengan pernyataan dokumentasi bahwa argumen terakhir dihitung setelah ekspansi.
EDITORadalah argumen untuk mengekspor