Kapan `_` variabel lingkungan dari sebuah bash shell?

10

Bash Manual mengatakan (halaman manual, penekanan saya):

Ketika Bash memanggil perintah eksternal, variabel $_diatur ke pathname lengkap dari perintah dan diteruskan ke perintah itu di lingkungannya.

Dan ( Parameter Khusus ):

_

( $_, sebuah garis bawah.) Pada startup shell, setel ke pathname absolut yang digunakan untuk memanggil shell atau skrip shell yang dieksekusi seperti yang diteruskan dalam lingkungan atau daftar 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.

  1. Di bash shell, saya menjalankan:

    $ bash
    $ export | grep '_=' 

    Menurut manual, _harus variabel lingkungan dari bash shell baru. exportseharusnya menampilkan semua variabel lingkungan dari bash shell baru, tetapi tidak menghasilkan _. Jadi saya bertanya-tanya apakah _variabel lingkungan dari bash shell baru?

  2. Sebenarnya di bash shell, hal yang sama terjadi

    $ export | grep '_='

    tidak menghasilkan apa-apa. Jadi saya bertanya-tanya apakah _pernah ada variabel lingkungan dari bash shell?

  3. Untuk perbandingan:

    $ dash
    $ export  | grep '_='        
    export _='/bin/dash'

Posting saya terinspirasi oleh komentar Mike dan balasan Stephane .

Tim
sumber
1
Ini adalah variabel shell, dan diteruskan ke lingkungan perintah ; itu belum tentu diekspor ke lingkungan shell . exportadalah builtin, tetapi jika Anda menggunakan printenv _, itu akan menunjukkan kepada Anda bagaimana itu dipanggil: /usr/bin/printenvpada sistem ini.
Toby Speight
Perhatikan bahwa bash -c export | grep _=(dari Bash), akan ditampilkan bagaimana shell induk menjalankan bashperintah, meskipun $_tidak disetel pada induknya.
Toby Speight

Jawaban:

13

Ya, _adalah variabel lingkungan dari shell Bash baru; Anda dapat melihatnya dengan menjalankan

tr '\0' '\n' < /proc/$$/environ | grep _=

di dalam shell: yang menunjukkan isi dari lingkungan awal shell. Anda tidak akan melihatnya di shell pertama karena tidak ada shell sebelumnya untuk mengaturnya sebelum dimulai.

Memperluas $_di dalam Bash mengacu pada _parameter khusus, yang memperluas argumen terakhir dari perintah sebelumnya. (Secara internal Bash menangani ini dengan menggunakan _variabel shell, yang diperbarui setiap kali perintah diuraikan, tapi itu benar-benar detail implementasi. Ini "tidak diekspor" setiap kali perintah diurai. ) exportTidak muncul _karena tidak variabel yang ditandai sebagai diekspor; Namun Anda dapat melihatnya di output dari set.

Dalam contoh pertama, shell Bash baru mem-parsing dan mengeksekusi perintah dalam file startupnya, jadi ketika berjalan explore | grep '-=', _sudah ditimpa dan ditandai sebagai tidak diekspor.

Dalam dashcontoh, sepertinya tidak menjalankan file start-up, jadi Anda melihat variabel sebagai variabel lingkungan yang ditetapkan oleh Bash sebelum dijalankan dash.

Stephen Kitt
sumber
Terima kasih. Di bash shell baru, mengapa tidak export | grep '_='menghasilkan apa-apa? Di bash shell asli, mengapa tidak tr '\0' '\n' < /proc/$$/environ | grep _=menghasilkan apa-apa?
Tim
9

exporttanpa argumen mendaftar semua variabel yang diekspor . _bukan variabel, tetapi terdaftar sebagai parameter khusus .

Agak membingungkan, _juga akan menjadi nama yang valid untuk suatu variabel , tidak seperti nama-nama parameter khusus lainnya. Setidaknya Bash 4.4 memungkinkan penugasan untuk itu, tanpa keluhan. Hanya saja tidak berguna karena efek khusus segera menimpa nilainya.

ilkkachu
sumber
2
Bersenang-senang mencoba untuk digunakan _sebagai variabel ;-). Secara efektif hanya menulis dan nilainya hilang dengan segera.
Stephen Kitt
1
Juga, secara internal Bash memperlakukan _sebagai variabel, itulah sebabnya ia muncul di output set. Namun itu tidak dapat ditandai sebagai diekspor sejauh yang saya bisa tentukan.
Stephen Kitt
2
@StephenKitt, tetapi Bash 4.4 memungkinkan menandainya hanya-baca. Atau bilangan bulat. Dengan hasil yang agak lucu.
ilkkachu
1
Ha, senang menemukan, itu agak lucu!
Stephen Kitt
5

Tidak semua variabel shell ditandai sebagai diekspor seperti yang Anda lihat di output declare -p.

Tidak masuk akal untuk bashmenandai $_sebagai diekspor karena secara otomatis menambahkan variabel ini ke lingkungan proses anak tetapi dengan nilai yang berbeda dari yang ada di shell (pada saat itu).

Menampilkannya sebagai yang diekspor hanya akan membingungkan pengguna tentang apa yang akan terjadi dengan lingkungan perintah eksternal.

Semua "variabel runtime" BASH*tidak diekspor.

Hauke ​​Laging
sumber