Penugasan variabel di luar pernyataan kasus

8

Dalam banyak bahasa dimungkinkan untuk menetapkan hasil dari pernyataan kasus / beralih ke variabel, daripada mengulangi penugasan variabel berkali-kali dalam pernyataan kasus. Apakah mungkin untuk melakukan hal seperti ini di shell Bash?

color_code=$(case "$COLOR" in
  (red)    1;;
  (yellow) 2;;
  (green)  3;;
  (blue)   4;;
esac)

(Atau, sebagai tambahan, di kulit lainnya?)

iconoclast
sumber
Anda memiliki tambahan (. Kalau tidak, tidak apa-apa.
HalosGhost

Jawaban:

6

The variable=$(...)membangun akan mengambil output standar perintah apa yang ada di $(...)dan menetapkan ke variable. Dengan demikian, untuk variableditugaskan seperti yang Anda inginkan, nilai-nilai harus dikirim ke output standar. Ini mudah dilakukan dengan echoperintah:

color_code=$(case "$COLOR" in
  red)    echo 1;;
  yellow) echo 2;;
  green)  echo 3;;
  blue)   echo 4;;
esac)

Ini akan bekerja pada bashserta semua kerang POSIX lainnya.

Opsional Left Parens

Menurut standar POSIX, paren kiri dalam casepernyataan adalah opsional dan yang berikut juga berfungsi:

color_code=$(case "$COLOR" in
  (red)    echo 1;;
  (yellow) echo 2;;
  (green)  echo 3;;
  (blue)   echo 4;;
esac)

Seperti yang ditunjukkan Gilles dalam komentar, tidak semua shell menerima kedua formulir dalam kombinasi dengan $(...): untuk tabel kompatibilitas yang sangat rinci, lihat "$ ()" substitusi perintah vs. tertanam ")" .

John1024
sumber
Satu halaman yang saya periksa (saya tidak ingat di mana tempatnya) mencantumkan pembukaan (sebagai opsional. Saya pikir itu mungkin membantu menghindari membiarkan )salah ditafsirkan sebagai penutup )untuk $(...)ekspresi.
iconoclast
@iconoclast Ya. Pembukaan (adalah opsional: kode berfungsi sama tanpa atau tanpa mereka. Saya meninggalkan mereka hanya karena, baik atau buruk, itu adalah tradisi. Bagian penting dari solusi yang diusulkan adalah penggunaan echo.
John1024
1
@iconoclast Kerang yang lebih lama (pra-POSIX) tidak mengizinkan pembukaan (untuk casepola, tetapi beberapa kerang melakukannya dan membutuhkan pembukaan (ketika casedigunakan dalam substitusi perintah. Kerang modern baik-baik saja. Lihat di-ulm.de/~mascheck/various/cmd-subst
Gilles 'SO- stop being evil'
1
@Gilles Terima kasih atas info itu. Kedalaman pengetahuan Anda, seperti biasa, mengesankan.
John1024
2

color_code=$(…)menugaskan output dari perintah ke variabel color_code, dengan baris baru dilucuti. Jadi, Anda perlu menghasilkan beberapa output. Kode yang Anda tulis mencoba dieksekusi 1sebagai perintah.

Anda bisa menggunakan idiom ini. Catatan yang color_codeakan kosong jika $COLORtidak ada nilai yang didukung.

color_code=$(case "$COLOR" in
  (red)    echo 1;;
  (yellow) echo 2;;
  (green)  echo 3;;
  (blue)   echo 4;;
esac)

Tapi itu tidak terlalu idiomatis. Bahasa shell diarahkan untuk kombinasi sederhana dari perintah sederhana. Substitusi perintah besar ini canggung. Substitusi perintah membuat subkulit, yang lebih lambat daripada metode langsung:

case "$COLOR" in
  red)    color_code=1;;
  yellow) color_code=2;;
  green)  color_code=3;;
  blue)   color_code=4;;
esac

Perbedaan semantik utama antara dua pendekatan adalah yang $(…)menciptakan subkulit, sehingga setiap penugasan, keluar, redirection, dll. Yang dilakukan di dalam tidak memiliki efek di luar.

Gilles 'SANGAT berhenti menjadi jahat'
sumber