Apa arti dari “_ =”?

29

Setelah saya menjalankan set -a var=99, saya dapat menemukan kalimat dalam output dari set:

...
TERM=xterm
UID=0
USER=root
VIRTUAL_ENV_DISABLE_PROMPT=1
_=var=99
colors=/etc/DIR_COLORS
...

Adakah yang bisa memberi tahu saya apa artinya "_ ="?

Saya perhatikan bahwa tidak echo $varakan memberikan apa-apa. Jika saya menjalankan set -a, maka settidak akan menyertakan variabel ini lagi. Apa yang terjadi?

Yode
sumber

Jawaban:

16

Ketika Anda mengeksekusi set -a var=99, tiga hal berbeda terjadi (terkait dengan pertanyaan Anda):

  1. Opsi yang disetel ( -a) (terbalik dengan melakukan set +a) untuk mengekspor vars.
  2. Parameter posisi "diatur" untuk mengikuti opsi ( $1set ke var=99).
  3. Garis bawah variabel shell $_diatur ke parameter terakhir (diperluas).

set -a

Eksekusi set -amenandai semua variabel berikutnya (baru atau diubah) yang diekspor (dalam semua shell, kecuali cshdan beberapa shell terkait).

$ set -a
$ myvariable=wer
$ env | grep myvariable
myvariable=wer

Untuk memulihkan dari pengaturan ini, cukup ubah -ke +:

$ set +a
$ unset myvariable              # to erase it from the environment if it
                                # was exported before the change of set +a
$ myvariable=456544654          # A new value of the variable.
$ env | grep "variable"         # No output means the var does not exist
                                # in the current environment

set var = 99

Yang sebenarnya harus set -- var=99menghindari interpretasi opsi (dan set memiliki banyak) dengan nilai-nilai yang dimulai dengan tanda hubung ( -).

Atur daftar argumen (daftar parameter posisi) ke yang setelah --. Itu berlaku di semua shell yang masuk akal (tidak dalam csh et al). Argumen posisional dicetak dengan "$ @" (atau "$ *" yang serupa, tidak sama).

$ set -- a=1 b=2 c=3
$ echo "$@"
a=1 b=2 c=3

_ = last_argument

Dan, nilai variabel shell internal _berubah menjadi argumen terakhir dari baris yang dieksekusi. Itu TIDAK benar di hampir semua shell (jsh, ash, yash, dash, lksh, mksh, ksh93, attsh dan tentu saja csh dan tcsh) kecuali bash.

$ echo one two last argument
one two last argument

$ echo "$_"
argument

$ echo This is a new: last_argument
This is a new: last_argument

$ echo "$_"
last_argument

Harap perhatikan bahwa nilai dalam $_adalah nilai setelah ekspansi:

$ a="A New_Argument"
$ echo Something else to test: "$a"
Something else to test: A New_Argument

$ echo "$_"
A New_Argument

Itu sebabnya ketika Anda mengeksekusi:

$ set -a myvar=99; set | grep 'myvar'
_=myvar=99

Anda mendapatkan deskripsi variabel shell '$ _'. Ini juga berfungsi:

$  set -a myvar=99; declare -p _
declare -- _="myvar=99"
Panah
sumber
37

Garis bawah sebenarnya adalah variabel shell khusus. Apa yang Anda lihat di sini adalah _variabel garis bawah ( ) dengan nilai var=99. Itu dibaca hanya, dan dikelola oleh shell. Ini:

  • Diatur pada startup shell, berisi nama file absolut dari shell atau skrip yang dieksekusi seperti yang diteruskan dalam daftar argumen.
  • Setelah itu, ia memperluas argumen terakhir ke perintah sebelumnya, setelah ekspansi.
  • Saat memeriksa email, parameter ini menyimpan nama file email.
  • Itu juga diatur ke pathname lengkap dari setiap perintah yang dieksekusi dan ditempatkan di lingkungan yang diekspor ke perintah itu.

Contoh Anda termasuk dalam kategori kedua. Anda mengetik:

set -a var=99  

Jadi argumen terakhir ada var=99, dan itu adalah nilai yang Anda tetapkan (Anda tidak menyetel varke 99). Oleh karena itu, _diatur untuk itu. Dan itulah yang dilaporkan:

_=var=99  

Agak membingungkan, tetapi yang pertama =menunjukkan tugas untuk variabel _, dan yang kedua adalah bagian dari nilai.

Perlu juga disebutkan bahwa -aopsi untuk setakan menyebabkan semua variabel yang didefinisikan selanjutnya diekspor.

Bob Eager
sumber
16

Jawaban yang tepat akan tergantung pada shell yang Anda gunakan:

  • untuk bash, apa pun yang dikatakan @BobEager berlaku
  • karena zsh, hanya disetel ke argumen terakhir dari perintah sebelumnya, dan ke pathname lengkap dari perintah di lingkungan perintah
  • beberapa shell seperti dashhanya mengatur variabel ini saat menjalankan sesi interaktif

Mungkin ada kekhasan lain dalam cangkang lain juga. Dengan demikian, $_ini tidak didefinisikan dalam POSIX, sehingga salah satu harus menyadari masalah portabilitas potensial ketika menggunakannya.

Catatan tambahan: jika maksud Anda adalah untuk menetapkan nilai 99 ke vardan membuatnya tersedia di lingkungan subproses berikutnya, sintaks yang benar untuk mencapai ini adalah:

export var=99
Dmitry Grigoryev
sumber
2
Sintaks yang benar juga unset var;set -a; var=99. Bekerja di semua cangkang resonable (bukan csh et al).
Panah
1
@Arrow Meskipun menurut baris terakhir dari jawaban Bob Eager ini akan membuat semua variabel selanjutnya diatur / dimodifikasi diekspor, yang mungkin bukan yang Anda inginkan.
TripeHound
8

Dan saya perhatikan tidak echo $varakan memberikan apa-apa. … Apa yang terjadi?

Dalam cetakan bash (1) yang tidak terlalu bagus , kami temukan

set[ --abefhkmnptuvxBCEHPT] [ opsi-nama ] [ arg …]   [ ] [ opsi-nama ] [ arg …]-o
set+abefhkmnptuvxBCEHPT+o

            ︙
    Ketika opsi ditentukan, mereka menetapkan atau membatalkan atribut shell. Argumen yang tersisa setelah pengolahan pilihan diperlakukan sebagai nilai untuk parameter posisi dan ditugaskan, dalam rangka, untuk $1, $2, ... .$n

Yang berarti, set -a var=99tidak mengatur variabel lingkungan varke 99; set $1ke var=99. Coba echo "$1"atau echo "$*"dan Anda akan melihat.

Scott
sumber