Bagaimana cara membuat `local` menangkap kode keluar?


11

Dalam proyek saya, saya memiliki cuplikan berikut:

local output="$(bash "${1##*/}")"
echo "$?"

Ini selalu mencetak nol karena local, bagaimanapun, menghapus localmenyebabkan $?variabel berperilaku dengan benar: yang mengasumsikan kode keluar dari subkulit.

Pertanyaan saya adalah: bagaimana saya bisa menjaga variabel ini tetap lokal sementara juga menangkap nilai keluar?


1
shellchecktidak hanya akan menangkap masalah ini tetapi menyarankan solusinya di unix.stackexchange.com/a/281749/24718 !
Waleed Khan

Jawaban:


16
#!/bin/bash
thing() {
   local foo=$(asjkdh) ret="$?"
   echo "$ret"
}

Ini akan bergema 127, kode kesalahan yang benar untuk "perintah tidak ditemukan".

Anda dapat menggunakan localuntuk mendefinisikan lebih dari satu variabel. Jadi saya juga membuat variabel lokal RETuntuk mengambil kode keluar dari subkulit sebelum localberhasil dan set $?ke nol.


Apakah dijamin bashmenilai ekspresi ini dari kiri ke kanan?
Max Ried

Sejauh yang saya ketahui, tugas variabel dalam urutan, kiri ke kanan dalam konteks ini, ya.
DopeGhoti

@ MaxRied fakta ini berfungsi andal akan muncul untuk menunjukkan bahwa ya, itu. Namun, saya tidak dapat menemukan informasi tentang ini baik dari bashmanual referensi POSIX maupun .
kucing

10
Selain itu, menggunakan nama variabel all-caps adalah bentuk yang buruk. Lihat spesifikasi variabel lingkungan POSIX di pubs.opengroup.org/onlinepubs/009695399/basedefs/… , yang menjelaskan nama semua huruf besar sebagai variabel yang dicadangkan untuk variabel dengan makna pada shell atau sistem dan nama dengan setidaknya satu karakter huruf kecil dicadangkan untuk penggunaan yang ditentukan aplikasi, mengingat bahwa variabel shell dan variabel lingkungan berbagi namespace (karena, jika terjadi tabrakan, penugasan ke yang pertama dapat menggantikan yang terakhir).
Charles Duffy

Komentar bukan untuk diskusi panjang; percakapan ini telah dipindahkan ke obrolan .
terdon

27

Nyatakan variabel lokal sebelum Anda menetapkannya:

thing() {
  local output
  output="$(bash "${1##*/}")"
  echo "$?"
}

Menurut pendapat saya ini juga lebih mudah dibaca daripada mengatur RETvariabel tambahan . YMMV tentang itu, tetapi berfungsi seperti yang Anda harapkan.


2
Ini jauh lebih baik daripada menggunakan variabel terpisah, seperti yang seharusnya jelas jika Anda ingin memeriksa kode pengembalian beberapa tugas: cukup local var1 var2 ...dan Bob adalah paman Anda.
l0b0

@ 10B0 Bob adalah pamanku. : D
cat
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.