Menginisialisasi variabel Bash - Apakah diperlukan, disarankan, atau ditentukan saat Anda mulai

9

Apakah ada keuntungan / kerugian dari menginisialisasi nilai variabel bash dalam skrip, baik sebelum kode utama, atau variabel lokal dalam suatu fungsi sebelum menetapkan nilai aktual ke dalamnya?

Apakah saya perlu melakukan sesuatu seperti ini:

init()
{
    name=""
    name=$1
}

init "Mark"

Apakah ada risiko variabel diinisialisasi dengan nilai-nilai sampah (jika tidak diinisialisasi) dan yang memiliki efek negatif dari nilai-nilai variabel?

Cyrus
sumber
2
Dari mana Anda mendapatkan ide ini?
6
@DoritoStyle Nah, jika seseorang digunakan untuk bahasa tingkat yang lebih rendah, seperti C, maka ini adalah hal yang benar-benar valid untuk diperhatikan.
Kusalananda
@ Kusalananda Bukankah C setara dengan kode itu name = ""; name = argv[1];? Dan bukankah itu tidak ada gunanya?
Joseph Sible-Reinstate Monica
1
@ JosephSible-ReinstateMonica Ya. Kode C yang Anda posting tidak ada gunanya. Namun, dalam C, berbeda dengan shell, variabel yang tidak diinisialisasi tidak memiliki nilai tertentu yang didefinisikan dengan baik. Ini berarti bahwa menginisialisasi variabel dalam bahasa seperti C masuk akal dalam banyak keadaan. Tidak perlu melakukannya di shell. Menginisialisasi variabel dalam C hanya untuk segera menetapkannya ke nilai lain tidak ada gunanya, seperti yang Anda tunjukkan.
Kusalananda

Jawaban:

22

Tidak ada manfaatnya untuk menetapkan string kosong ke variabel dan kemudian segera menetapkan string variabel lain untuk itu. Penugasan nilai ke variabel shell akan sepenuhnya menimpa nilai sebelumnya.

Setahu saya tidak ada rekomendasi yang mengatakan bahwa Anda harus secara eksplisit menginisialisasi variabel ke string kosong. Bahkan, melakukan hal itu dapat menutupi kesalahan dalam beberapa keadaan (kesalahan yang akan terlihat jika berjalan di bawah set -u, lihat di bawah).

Variabel yang tidak disetel, tidak digunakan sejak awal skrip atau secara eksplisit tidak disetel dengan menjalankan unsetperintah di atasnya, tidak akan memiliki nilai. Nilai variabel semacam itu tidak akan berarti apa-apa. Jika digunakan sebagai "$myvariable", Anda akan mendapatkan yang setara dengan "", dan Anda tidak akan pernah mendapatkan "data sampah".

Jika opsi shell nounsetdiatur dengan salah satu set -o nounsetatau set -u, maka referensi variabel yang tidak disetel akan menyebabkan shell menghasilkan kesalahan (dan shell non-interaktif akan berakhir):

$ set -u
$ echo "$myvariable"
/bin/sh: myvariable: parameter not set

atau, di bash:

$ set -u
$ echo "$myvariable"
bash: myvariable: unbound variable

Variabel Shell akan diinisialisasi oleh lingkungan jika nama variabel sesuai dengan variabel lingkungan yang ada.

Jika Anda berharap bahwa Anda menggunakan variabel yang dapat diinisialisasi oleh lingkungan dengan cara ini (dan jika tidak diinginkan), maka Anda dapat menghapusnya secara eksplisit di depan bagian utama skrip Anda:

unset myvariable    # unset so that it doesn't inherit a value from the environment

yang juga akan menghapusnya sebagai variabel lingkungan, atau, Anda dapat mengabaikan nilai awal dan hanya menimpanya dengan tugas (yang akan membuat nilai perubahan variabel lingkungan juga).

Anda tidak akan pernah menemukan sampah yang tidak diinisialisasi dalam variabel shell (kecuali, seperti yang disebutkan, bahwa sampah sudah ada di variabel lingkungan dengan nama yang sama).

Kusalananda
sumber
3
Meskipun tidak ada nilai untuk mengatur variabel ke nilai kosong dan kemudian segera mengaturnya seperti OP secara harfiah, ada nilai dalam menetapkan nilai kosong (atau unsetting) sebelum menjalankan beberapa jenis foratau whileloop untuk mengaturnya ke perhitungan nilai jika ada kemungkinan loop tidak akan benar-benar berjalan karena kondisi tidak terpenuhi; dan variabel mungkin telah diatur ke beberapa nilai lain di lingkungan skrip yang diwarisi. Tapi ini bisa dibilang lebih baik untuk meletakkan segala sesuatu di dalam main()dan mendefinisikan variabel sebagai local.
Monty Harder
Anda juga dapat mendeteksi variabel yang tidak disetel menggunakan operator ekspansi parameter, dengan menghilangkan :, misalnya${myvariable-defaultvalue}
Barmar
3

Sunting : Whoops, ternyata deklarasi berbeda dari inisialisasi. Saya akan meninggalkan ini di sini sehingga coders pemula seperti saya dapat belajar dari kesalahan saya.


Keuntungan dari mendeklarasikan variabel lokal dalam suatu fungsi adalah Anda dapat dengan mudah menyalin kode.

Misalnya, katakan saya memiliki fungsi:

foo(){
    local name
    name="$1"
    echo "$name"
}

Jika saya ingin membuatnya menjadi skrip, saya mengabaikan saja localpernyataan itu dan menyalin yang lainnya:

#!/bin/bash
name="$1"
echo "$name"

Jika deklarasi dan penugasan berada di baris yang sama, saya harus mengedit localbagian secara manual sebelum saya bisa mengubahnya menjadi skrip:

foo(){
    local name="$1"
    echo "$name"
}

Dalam contoh ini ini bukan masalah besar, tetapi jika Anda berurusan dengan fungsi yang lebih besar, lebih kompleks, itu bisa menjadi lebih menyakitkan.

wjandrea
sumber
1
Pertanyaannya bukan tentang menggabungkan deklarasi dan inisialisasi. Itu tentang apakah akan menginisialisasi dengan nilai kosong sebelum menetapkan nilai nyata.
Barmar
@Barmar Oh, saya baru saja mencari "inisialisasi". Saya pikir itu identik dengan "deklarasi" ...
wjandrea