$_
dikatakan sebagai argumen terakhir dari perintah sebelumnya.
Jadi saya bertanya-tanya mengapa itu tidak ada EDITOR="emacs -nw"
tetapi EDITOR
dalam contoh berikut?
Mengapa bukan "emacs -nw"
bagian dari argumen terakhir?
Secara umum, apa definisi argumen, dan argumen terakhir?
Terima kasih.
$ export EDITOR="emacs -nw"
$ echo $_
EDITOR
EDITOR
adalah argumen untuk mengeksporpdksh
dandash
akan mencakup nilai yang ditugaskan, tetapiksh93
akan berperilaku sepertibash
halnya.export FOO=bar; echo $_
mencetakexport
.export
adalah utilitas bawaan.typeset -x FOO=bar
laluecho $_
dicetakFOO
, tetapi dalamdeclare -x FOO=bar; echo $_
cetak BashFOO=bar
.Jawaban:
Bash memproses tugas variabel, ketika mereka diizinkan sebagai argumen (dengan
alias
,declare
,export
,local
,readonly
, dantypeset
), sebelum hal lain (atau lebih tepatnya, itu mengidentifikasi mereka sebelum hal lain - ekspansi berlaku untuk nilai-nilai ditugaskan untuk variabel). Ketika sampai ke ekspansi kata, perintah yang tersisa adalahexport EDITOR
, jadi_
diatur keEDITOR
.Secara umum, argumen adalah "kata-kata" yang tersisa setelah ekspansi (yang tidak termasuk tugas variabel dan pengalihan).
Lihat Ekspansi perintah sederhana di manual Bash untuk detailnya.
sumber
declare
perilaku tidak sesuai dengan apa yang saya gambarkan ...declare a=b; echo $_
cetakana=b
;export c=d; echo $_
hanya mencetakc
.alias
tampaknya hanya mencetak nama,local
di sisi lain mencetak seluruh argumen. Danreadonly
juga mencetak hanya nama, yang saya temukan sedikit mengejutkan karena saya akan berpikirreadonly
danlocal
akan miripdeclare
.export
danreadonly
dinyatakan bersama-sama dalamsetattr.def
,declare
,local
, dantypeset
dinyatakan dalamdeclare.def
,alias
berdiri sendiri dialias.def
.alias, declare, export, local, readonly
dantypeset
. Apa yang terjadi pertama dan selanjutnya? "Ketika sampai pada kata ekspansi, perintah yang tersisa adalahexport EDITOR
", apakah Anda menyiratkan bahwa penugasan variabelEDITOR="emacs -nw"
terjadi sebelum ekspansi? Jika tidak, mengapa perintah yang tersisa tidak berisi tugas sebagai argumen? Jika ya, bukankah ekspansi pada nilai yang ditugaskan ke variabel harus terjadi sebelum melakukan penugasan variabel?TL; DR: Dalam kasus
export FOO=bar
, bash memanggil penciptaan lingkungan sementara, menetapkanFOO=bar
dalam lingkungan itu, lalu menghasilkan perintah terakhir dariexport FOO
. Pada titik itu,FOO
diambil sebagai argumen terakhir.Ah, yang paling banyak disalahgunakan
$_
:Mari kita lihat beberapa variasi:
Jadi kita melihat tiga pola di sini:
$_
diatur ke nama perintah itu sendiri jika tidak ada argumen, kalau tidak argumen terakhir yang disajikan.$_
tidak diubah.$_
diatur ke sesuatu yang tidak terlalu diharapkan; aneh.Saya telah memasukkan kode untuk memberikan wawasan tentang keanehan.
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.sumber
MAILCHECK
Untuk menjawab pertanyaan judul, cobalah
!$
:Ini adalah ekspansi sejarah. Dari halaman bash:
...
...
...
...
...
...
sumber
export EDITOR="emacs -nw"
» terdiri dari dua kata: yang pertama adalah «export
» dan yang kedua adalah «EDITOR="emacs -nw"
». Pertanyaannya adalah benar-benar bertanya, "Apa yang dimaksud dengan halaman bash man dan Manual Bash ketika mereka mengatakan bahwa!_
'memperluas argumen terakhir ke perintah sebelumnya', mengingat bahwa bash menetapkan$_
«EDITOR
dalam kasus ini? " Menyalin dan menempelkan bagian halaman bash man tentang ekspansi sejarah tidak terlalu membantu.