Di mana "ekspor var = nilai" tidak tersedia?

31

Saya telah mengambil - mungkin di Usenet pada pertengahan 1990-an (!) - yang membangun

export var=value

adalah Bashism, dan ungkapan portabel itu

var=value
export var

Saya telah mengadvokasi ini selama bertahun-tahun, tetapi baru-baru ini, seseorang menantangku, dan saya benar-benar tidak dapat menemukan dokumentasi untuk mendukung apa yang dulunya merupakan kepercayaan kuat saya.

Googling untuk "export: command not found"sepertinya tidak memunculkan kasus di mana seseorang benar-benar memiliki masalah ini, jadi meskipun itu asli, saya kira itu tidak terlalu umum.

(Hits saya mendapatkan tampaknya pemula yang menyalin / disisipkan tanda baca, dan berakhir dengan 'export: command not foundatau semacam, atau mencoba untuk menggunakan exportdengan sudo, dan pemula csh. Pengguna mencoba untuk menggunakan Bourne shell sintaks)

Saya pasti bisa mengatakan bahwa ia bekerja pada OS X, dan pada berbagai distro Linux, termasuk yang mana shadalah dash.

sh$ export var=value
sh$ echo "$var"
value
sh$ sh -c 'echo "$var"'  # see that it really is exported
value

Dalam dunia sekarang ini, apakah aman untuk mengatakan bahwa export var=valueitu aman untuk digunakan?

Saya ingin memahami apa konsekuensinya. Jika tidak portabel untuk v7 "Bourne classic", itu hampir tidak lebih dari hal sepele. Jika ada sistem produksi di mana shell benar-benar tidak dapat mengatasi sintaks ini, itu akan berguna untuk diketahui.

tripleee
sumber
2
terima kasih saya akhirnya mengerti mengapa saya melihat begitu sering hal yang saya pikir tidak berguna: var = nilai; ekspor var
Thorsten Staerk
2
Masih ada beberapa kotak Solaris yang ditendang, dan mereka terkenal hemat dalam alat standar mereka; di ujung lain dari spektrum, tidak busyboxdatang dengan cangkang minimal sendiri? (Saya tidak dalam posisi untuk mencoba saat ini juga.)
Ulrich Schwarz
Terima kasih Ulrich, Solaris mungkin menjadi penyebab mengapa sintaks yang panjang ini masih ada.
Thorsten Staerk

Jawaban:

20
export foo=bar

tidak didukung oleh shell Bourne (shell lama dari tahun 70an yang darinya shimplementasi modern seperti ash / bash / ksh / yash / zsh berasal). Itu diperkenalkan oleh ksh.

Di shell Bourne, Anda akan melakukan:

foo=bar export foo

atau:

foo=bar; export foo

atau dengan set -k:

export foo foo=bar

Sekarang, perilaku:

export foo=bar

bervariasi dari shell ke shell.

Masalahnya adalah bahwa penugasan dan argumen perintah sederhana diuraikan dan ditafsirkan secara berbeda.

Di foo=baratas ditafsirkan oleh beberapa shell sebagai argumen perintah dan oleh orang lain sebagai tugas (kadang-kadang).

Contohnya,

a='b c'
export d=$a

diartikan sebagai:

'export' 'd=b' 'c'

dengan beberapa shell ( ash, versi lama zsh(dalam emulasi sh), yash) dan:

'export' 'd=b c'

yang lain ( bash, ksh).

Sementara

export \d=$a

atau

var=d
export $var=$a

akan diinterpretasikan sama di semua shell (as 'export' 'd=b' 'c') karena backslash atau tanda dolar menghentikan shell yang mendukungnya untuk mempertimbangkan argumen tersebut sebagai tugas.

Jika exportitu sendiri dikutip atau hasil dari beberapa ekspansi (bahkan sebagian), tergantung pada shell, itu juga akan berhenti menerima perlakuan khusus.

Lihat " Apakah kutipan diperlukan untuk penugasan variabel lokal? " Untuk detail lebih lanjut tentang itu.

Sintaks Bourne:

d=$a; export d

ditafsirkan sama oleh semua shell tanpa ambiguitas ( d=$a export djuga akan bekerja di shell Bourne dan POSIX compliant tetapi tidak dalam versi terbaru zshkecuali dalam shemulasi).

Itu bisa menjadi jauh lebih buruk dari itu. Lihat misalnya diskusi terkini tentangbash kapan array terlibat.

(IMO, itu adalah kesalahan untuk memperkenalkan fitur itu ).

Stéphane Chazelas
sumber
Saya terkejut bahwa tanda titik koma tidak diperlukan foo=bar export foo, karena saya selalu melihatnya di sana. Saya tahu ekspor adalah standar, tetapi mengapa foo=bar; foo=baz export foo; echo $fooberperilaku berbeda dari foo=bar; foo=baz /bin/cat /dev/null; echo $foo?
jrw32982 mendukung Monica
3
@ jrw32982, karena itu builtin. Anda masih mendapatkan bahwa dalam kerang POSIX modern tetapi hanya untuk khusus builtin yang exportmerupakan.
Stéphane Chazelas
Meskipun membahas declare, tidak export, saya sarankan siapa pun yang peduli tentang keamanan membaca diskusi di tautan yang disediakan StéphaneChazelas kepada bash.bugs .
John1024
Jawaban bagus! Tapi butuh waktu lama untuk bisa d=$a export ddiartikan sama oleh semua kerang tanpa ambiguitas ;-)
conny
@conny, d=$a export dtidak berfungsi lagi zsh, jadi saya sudah memperbarui jawabannya. Lihat edit.
Stéphane Chazelas
28

Ini bukan bashism tapi sintaks yang sesuai dengan POSIX. Ini sebenarnya dimulai sebagai kshism cukup lama dan kemudian diadopsi oleh hampir semua cangkang sintaksis Bourne. Satu-satunya pengecualian yang terkenal adalah /bin/shpada Solaris 10 dan lebih lama yang melekat pada sintaksis Bourne shell lama. Semoga, Solaris 11 menggunakan shell yang sesuai dengan POSIX /bin/sh.

Ngomong-ngomong, exportsudah ada perintah builtin di shell Bourne warisan sehingga googling export: command not foundadalah menyesatkan.

Berikut adalah perilaku shell Bourne warisan ketika exportdikombinasikan dengan sebuah kepura-puraan:

$ export var=22
var=22: is not an identifier

Untuk nostalgia, kode sumber shell Bourne asli ini tersedia dan dapat dikompilasi untuk sebagian besar distribusi Unix dan Linux.

Jlliagre
sumber
Terima kasih banyak atas wawasan historis dan pesan kesalahan yang benar dari Google untuk! Jelas dalam retrospeksi, blush ...
tripleee
4
Itu bukan kode sumber dari shell Bourne asli, itu adalah OpenSolaris sh yang dimodifikasi. Itu adalah cangkang Bourne tetapi setelah mengalami beberapa dekade evolusi. Cangkang Bourne asli, sebagaimana dikirimkan bersama Unix V7 dapat ditemukan di Unix Heritage Society
Stéphane Chazelas
1
@ StéphaneChazelas Sebenarnya, Anda seperti biasa benar. Namun perlu dicatat bahwa saya tidak menulis "shell Bourne asli" tetapi "shell Bourne asli ini" karena saya mengacu pada shell yang digunakan oleh Solaris 10 dan kode sumbernya yang dapat dikompilasi pada platform modern. Perhatikan juga bahwa cangkang Bourne memiliki beberapa fitur yang ditambahkan antara 1977 dan 1989 tetapi pada dasarnya berhenti berkembang (di luar porting / beradaptasi dengan platform yang lebih baru dan perbaikan bug) dalam 25 tahun terakhir atau lebih.
jlliagre