Skrip menjadi lebih berguna ketika jalannya menyesuaikan diri dengan keadaan, misalnya memeriksa nilai sebelum menentukan predikat atau menguji keberadaan berkas sebelum membacanya. Topik ini membahas pernyataan if beserta cara bash menyusun kondisi, yaitu operator pengujian pada test, [ ], dan [[ ]], termasuk pengujian keberadaan dan jenis berkas. Keputusan sederhana dapat ditulis dalam skrip dengan struktur yang benar.
Pernyataan if#
Pernyataan if menjalankan blok perintah hanya apabila kondisinya berhasil. Kondisi tersebut adalah perintah biasa, dan bash menentukan keberhasilannya dari kode keluar, yaitu angka yang ditinggalkan setiap perintah ketika selesai. Kode keluar 0 berarti berhasil, sedangkan kode keluar selain 0 berarti gagal. Struktur paling sederhananya berbunyi if kondisi; then perintah; fi, yang dalam bentuk beberapa baris ditulis sebagai berikut.
# pernyataan if menjalankan blok hanya bila kondisinya berhasil
NILAI=87
if [[ $NILAI -ge 75 ]]; then
printf 'nilai %d dinyatakan lulus\n' "$NILAI"
finilai 87 dinyatakan lulusKondisi -ge 75 menguji apakah NILAI lebih besar atau sama dengan 75, dan karena 87 memenuhi syarat, blok di antara then dan fi dijalankan. Apabila kondisinya tidak terpenuhi, bash melewati blok itu tanpa pesan apa pun dan skrip berlanjut ke perintah setelah fi. Kata then menutup baris kondisi, sementara fi menandai akhir pernyataan if. Bentuk satu baris dengan titik koma tersebut hanya untuk merangkum strukturnya, sedangkan penulisan beberapa baris seperti contoh di atas lebih mudah dibaca dan menjadi kebiasaan yang baik.
Blok di antara then dan fi boleh memuat sejumlah perintah, termasuk pernyataan if lain yang bersarang di dalamnya. Kondisi yang dipilih juga bebas, yaitu pengujian [[ ]], perintah biasa, maupun gabungan keduanya, karena bash hanya menanyakan kode keluarnya. Cara pandang ini penting, karena seluruh keluarga percabangan bash bertumpu pada satu pertanyaan sederhana, yaitu apakah perintah kondisinya berhasil.
test, [ ], dan [[ ]]#
Tiga bentuk pengujian tersedia pada bash. Bentuk tertua adalah perintah test, yang kemudian mendapat alias [ ] agar mirip kurung, sedangkan bash menyediakan kata kunci [[ ]] sebagai perluasannya. Ketiganya menguji ekspresi dan meninggalkan kode keluar 0 apabila ekspresi benar. Perbedaan yang paling terasa ada pada variabel yang kosong atau berisi spasi.
Pemeriksaan [ ] memperlakukan hasil ekspansi sebagai kata-kata terpisah, sehingga variabel kosong yang ditulis tanpa quoting menyebabkan struktur ujiannya rusak. Demonstrasi berikut membandingkan kedua bentuk pada variabel yang sama.
# uji [ ] dengan variabel kosong tanpa quoting, lalu bandingkan dengan [[ ]]
KOTA=""
[ $KOTA = "Bandung" ] || printf 'pemeriksaan [ ] tanpa quoting gagal\n'
[[ $KOTA = "Bandung" ]] || printf 'perbandingan [[ ]] berjalan lancar, hasilnya tidak sama\n'bash: line 10: [: =: unary operator expected
pemeriksaan [ ] tanpa quoting gagal
perbandingan [[ ]] berjalan lancar, hasilnya tidak samaBaris pertama menghasilkan pesan unary operator expected karena [ ] hanya menerima satu kata di posisi kiri setelah pecah kata, yaitu tanda = yang dianggap operator tanpa perbandingannya. Tanda || setelahnya berfungsi sebagai logika atau, yaitu menjalankan perintah di kanannya hanya apabila perintah di kirinya gagal. Bentuk [[ ]] pada baris kedua tidak mengalami pecah kata, sehingga perbandingan berjalan lancar dan hasilnya memang berbeda karena nilai kosong tidak sama dengan Bandung.
Untuk skrip bash, bentuk [[ ]] adalah pilihan yang disarankan karena lebih aman terhadap nilai berisi spasi dan menyediakan operator logika di dalamnya. Bentuk [ ] tetap perlu dikenali karena banyak skrip lama menggunakannya.
Operator pengujian#
Operator pengujian dikelompokkan menurut jenis nilainya. Perbandingan angka menggunakan operator yang berbeda dari perbandingan teks, dan masing-masing memiliki arti yang tetap.
| Operator | Jenis | Arti |
|---|---|---|
-eq, -ne | angka | sama dengan, tidak sama dengan |
-lt, -le | angka | lebih kecil, lebih kecil atau sama dengan |
-gt, -ge | angka | lebih besar, lebih besar atau sama dengan |
=, != | teks | sama dengan, tidak sama dengan |
-z, -n | teks | kosong, tidak kosong |
-e, -f, -d | berkas | ada, berkas biasa, direktori |
Operator angka menjalankan perbandingan aritmetika, sehingga -lt pada 9 dan 10 bernilai benar. Operator teks membandingkan isi string sepenuhnya. Demonstrasi berikut mencoba beberapa operator pada satu variabel angka.
# operator aritmetika pada [[ ]]
ANGKA=10
[[ $ANGKA -eq 10 ]] && printf 'ANGKA sama dengan sepuluh\n'
[[ $ANGKA -lt 5 ]] || printf 'ANGKA tidak lebih kecil dari lima\n'ANGKA sama dengan sepuluh
ANGKA tidak lebih kecil dari limaTanda && berlaku sebagai logika dan, yaitu menjalankan perintah di kanannya hanya apabila perintah di kirinya berhasil. Pada baris pertama, perbandingan bernilai benar sehingga printf dijalankan, sedangkan pada baris kedua perbandingan bernilai salah sehingga perintah setelah || yang dijalankan. Dua pasangan ini menjadi cara ringkas untuk menuliskan keputusan satu baris tanpa struktur if yang lengkap.
Pengujian keberadaan dan jenis berkas#
Operator pengujian berkas memeriksa isi disk sebelum skrip membaca atau menulisnya. Operator -e menguji keberadaan tanpa melihat jenisnya, -f menguji berkas biasa, dan -d menguji direktori. Siapkan dahulu satu berkas dan satu direktori contoh, lalu uji keduanya.
# siapkan berkas dan direktori untuk pengujian
printf 'satu\n' > catatan.txt
mkdir -p arsip# operator -f menguji berkas biasa, -d menguji direktori
[[ -f catatan.txt ]] && printf 'catatan.txt adalah berkas biasa\n'
[[ -d arsip ]] && printf 'arsip adalah direktori\n'
[[ -f arsip ]] || printf 'arsip bukan berkas biasa\n'catatan.txt adalah berkas biasa
arsip adalah direktori
arsip bukan berkas biasaBaris ketiga penting untuk diamati, karena direktori arsip memang ada, tetapi tidak lolos uji -f yang khusus untuk berkas biasa. Pemilihan operator yang tepat memengaruhi jalannya skrip, misalnya pembacaan isi hanya boleh dilakukan pada berkas yang lolos uji -f, sementara penyimpanan hasil kerja sebaiknya diarahkan ke direktori yang lolos uji -d. Operator pengujian berkas lainnya, seperti -s untuk berkas yang tidak kosong dan -r untuk berkas yang dapat dibaca, mengikuti pola yang sama.
Pengujian jenis berkas menjadi pelindung pertama sebelum perintah yang berdampak dijalankan. Skrip yang menyalin atau menghapus berkas lebih aman apabila menguji -f lebih dahulu, karena perintah tersebut tidak memeriksa jenis targetnya dan langsung bekerja pada argumen yang diberikan. Kebiasaan yang sama berlaku untuk masukan pengguna, misalnya jalur berkas yang diterima skrip sebelum diolah, sebab jalur yang salah diketik tidak akan terlihat tanpa pengujian. Dengan uji keberadaan dan jenis di awal skrip, pesan kesalahan yang muncul pun menjadi lebih jelas arah penyebabnya.
if, elif, else#
Struktur if yang lengkap memiliki tiga jalur, yaitu then untuk kondisi terpenuhi, elif untuk kondisi berikutnya yang diperiksa berurutan, dan else untuk sisa kasus. Bash menghentikan pemeriksaan pada kondisi pertama yang terpenuhi, sehingga urutan kondisi menentukan hasilnya. Skrip berikut menerapkan struktur itu untuk menentukan predikat sebuah nilai ujian.
#!/usr/bin/env bash
# laporan-nilai.sh: menentukan predikat dari sebuah nilai ujian
set -euo pipefail
NILAI=87
if [[ $NILAI -ge 85 ]]; then
PREDIKAT="A"
elif [[ $NILAI -ge 70 ]]; then
PREDIKAT="B"
elif [[ $NILAI -ge 60 ]]; then
PREDIKAT="C"
else
PREDIKAT="D"
fi
printf 'Nilai %d memperoleh predikat %s\n' "$NILAI" "$PREDIKAT"# jalankan skrip penentu predikat
bash laporan-nilai.shNilai 87 memperoleh predikat ANilai 87 lolos pada kondisi pertama, sehingga dua kondisi berikutnya tidak pernah diperiksa. Untuk melihat jalur yang lain, struktur yang sama diuji ulang dengan angka yang lebih kecil.
# jalur elif dan else dengan nilai berbeda
NILAI=64
if [[ $NILAI -ge 85 ]]; then
PREDIKAT="A"
elif [[ $NILAI -ge 70 ]]; then
PREDIKAT="B"
else
PREDIKAT="C"
fi
printf 'nilai %d memperoleh predikat %s\n' "$NILAI" "$PREDIKAT"nilai 64 memperoleh predikat CNilai 64 gagal pada dua kondisi pertama dan berlanjut ke else, yang tidak memuat kondisi apa pun dan selalu dijalankan apabila seluruh kondisi di atasnya gagal. Apabila predikat berkebalikan, misalnya rentang yang lebih kecil diuji lebih dahulu, urutan kondisi harus disusun ulang agar hasilnya tetap benar. Urutan penyusunan kondisi rentang disarankan mengikuti satu arah yang konsisten, misalnya dari tinggi ke rendah atau sebaliknya, agar skripnya mudah dibaca ulang.
Jumlah elif tidak dibatasi, sehingga klasifikasi dengan banyak tingkatan tetap berbentuk satu pernyataan if. Apabila else tidak ditulis dan tidak ada kondisi yang terpenuhi, seluruh blok dilewati tanpa pesan, yang kadang memang disengaja dan kadang menyembunyikan kasus yang terlupakan. Menulis else yang berisi pesan atau tindakan bawaan membuat kasus tidak terduga selalu terlihat. Keputusan tersebut diserahkan pada kebutuhan skrip yang sedang ditulis.
Kesalahan umum#
Kata kunci yang hilang atau salah tempat. Setiap if membutuhkan then dan ditutup dengan fi, sedangkan setiap elif membutuhkan kondisinya sendiri. Ketiadaan salah satu bagian menghasilkan pesan sintaks yang menyebut kata terakhir berkas, dan pesan tersebut sering menunjuk baris setelah akar masalahnya. Memeriksa pasangan if, then, dan fi pada penyuntingan yang menambah atau menggeser blok merupakan langkah pertama yang tepat.
Pemeriksaan [ ] tanpa quoting pada variabel yang mungkin kosong. Variabel kosong yang diekspansi tanpa kutip ganda hilang dari ekspresi sehingga struktur [ ] kehilangan salah satu sisi perbandingannya. Pesan unary operator expected pada bagian test, [ ], dan [[ ]] merupakan contohnya. Perbaikannya adalah menuliskan variabel dengan kutip ganda, atau berpindah ke [[ ]] yang tidak memecah kata.
Operator yang tidak sesuai jenisnya. Operator -eq dan kawan-kawannya hanya berlaku untuk angka, sedangkan = hanya berlaku untuk teks. Membandingkan teks dengan operator angka menghasilkan pesan error tentang ekspresi bilangan, dan membandingkan angka dengan = menghasilkan perbandingan teks yang mudah salah. Pilih operator sesuai jenis nilai yang diujikan.
Ringkasan#
- Pernyataan if menentukan blok yang dijalankan berdasarkan kode keluar kondisinya, dengan 0 sebagai tanda keberhasilan.
- Bentuk
[[ ]]adalah pengujian bawaan bash yang aman terhadap pecah kata, sedangkantestdan[ ]adalah bentuk lama yang masih banyak digunakan. - Operator pengujian terbagi untuk angka, teks, dan berkas, termasuk
-funtuk berkas biasa dan-duntuk direktori. - Struktur
if,elif, danelsemenyusun keputusan berlapis, dan bash berhenti pada kondisi pertama yang terpenuhi.
Referensi#
- GNU Bash Reference Manual — Free Software Foundation
— dokumentasi resmi bash untuk konstruksi kondisional, termasuk
ifdan[[ ]]. - Google Shell Style Guide — Google
— bagian Tests yang menganjurkan
[[ ]]untuk skrip bash beserta aturan operatornya.