Percabangan

if, test, dan [[ ]], serta perbandingan string dan angka.

Daftar isi

Percabangan membuat skrip memilih jalur berbeda sesuai hasil pemeriksaan sebuah syarat, alih-alih menjalankan semua perintahnya secara lurus. Topik ini membahas pernyataan if, perintah test beserta bentuk kurung sikunya, operator perbandingan angka dan string, serta konstruksi [[ ]] yang khas bash. Contohnya berupa skrip pemberi keputusan sederhana yang dipanggil dengan argumen berbeda-beda, disertai percobaan pemeriksaan yang terpisah dari skripnya.

Pernyataan if dan status keluar#

Pernyataan if menjalankan sebuah perintah, lalu memilih cabang berdasarkan status keluar (exit status) perintah itu, yaitu angka nol untuk berhasil dan angka lain untuk gagal. Cabang then dieksekusi ketika statusnya nol, sedangkan elif dan else menampung pemeriksaan lanjutan beserta pilihan terakhir. Struktur ini ditutup dengan fi.

Skrip berikut mengelompokkan nilai ujian ke dalam dua kategori dan menampilkan pesan cara pakai apabila dipanggil tanpa argumen:

bash nilai.sh
#!/bin/bash
# mengkategorikan nilai ujian dari argumen pertama

nilai="$1"

if [ -z "$nilai" ]; then
    echo "Cara pakai: nilai.sh <angka 0-100>"
elif [ "$nilai" -ge 75 ]; then
    echo "Nilai $nilai: tuntas"
else
    echo "Nilai $nilai: belum tuntas"
fi
text Keluaran
Cara pakai: nilai.sh <angka 0-100>

Panggilan tanpa argumen membuat pemeriksaan -z bernilai benar karena variabel nilai kosong, sehingga skrip masuk ke cabang pertama. Uji berikut menyiapkan folder kerja lalu memanggil skrip yang sama dengan dua nilai berbeda:

bash
# folder kerja latihan
mkdir -p /tmp/kerja-percabangan
# menyalin skrip ke folder kerja lalu masuk ke sana
cp nilai.sh /tmp/kerja-percabangan/
cd /tmp/kerja-percabangan
# memanggil skrip dengan dua nilai berbeda
bash nilai.sh 80
bash nilai.sh 60
text Keluaran
Nilai 80: tuntas
Nilai 60: belum tuntas

Nilai 80 lolos pada pemeriksaan -ge 75 sehingga masuk cabang elif, sedangkan 60 gagal di sana dan jatuh ke else. Argumen pertama skrip dibaca melalui $1 dan disimpan ke variabel nilai pada baris awal supaya pemeriksaannya mudah dibaca. Pola membaca argumen terlebih dahulu lalu memeriksanya dengan if inilah bentuk percabangan yang paling umum pada skrip shell.

Perintah test dan bentuk [ ]#

Pemeriksaan pada if dikerjakan oleh sebuah perintah, dan perintah klasik untuk hal itu adalah test. Perintah ini menilai ekspresi yang diberikan lalu melaporkan hasilnya lewat status keluar, yaitu nol untuk benar dan satu untuk salah, tanpa mencetak apa pun. Bentuk [ ] adalah nama lain test dengan satu syarat tambahan, yaitu tanda kurung penutup, dan keduanya menuntut spasi di sekitar setiap operandnya.

Status keluarnya dapat dibaca langsung dengan $? sehingga perilaku test dapat dicoba tanpa skrip:

bash
# perbandingan angka dengan test
test 10 -eq 10
echo $?
test 7 -ge 10
echo $?
text Keluaran
0
1
bash
# perbandingan string dengan bentuk [ ]
[ "bash" = "bash" ]
echo $?
[ "bash" = "sh" ]
echo $?
text Keluaran
0
1

Bentuk yang sama digunakan untuk memeriksa keberadaan berkas, dan pemeriksaan semacam ini menjadi syarat yang paling sering digunakan sebelum skrip memproses berkas yang dituju. Operator -f bernilai benar ketika jalurnya adalah berkas biasa yang ada, sedangkan -d untuk direktori dan -e untuk keberadaan apa pun:

bash
# pemeriksaan keberadaan berkas
[ -f /etc/hosts ]
echo $?
[ -f /etc/tidak-ada ]
echo $?
text Keluaran
0
1

Pada penerapan nyata, kelompok perintah ini jarang ditulis bersama echo $? karena if sudah membaca statusnya secara langsung. Percobaan terpisah seperti di atas tetap berguna ketika merancang syarat yang rumit, karena jawaban benar-salahnya terlihat tanpa perlu menjalankan seluruh skrip. Kebiasaan menguji syaratnya lebih dahulu mengurangi error yang baru ketahuan di tengah skrip.

Operator perbandingan angka dan string#

test memisahkan operator untuk angka dan operator untuk string, dan mencampuradukkan keduanya adalah sumber error yang lazim. Perbandingan angka menggunakan -eq, -ne, -lt, -le, -gt, dan -ge, sedangkan perbandingan string menggunakan = dan !=. Tabel berikut merangkum keduanya.

Operator angkaArtiPadanan string
-eqsama dengan=
-netidak sama dengan!=
-ltlebih kecil<
-lelebih kecil atau sama dengantidak tersedia
-gtlebih besar>
-gelebih besar atau sama dengantidak tersedia

Perbandingan string < dan > menilai urutan teks menurut kamus, bukan besaran angka. Di dalam [ ], kedua operator ini harus ditulis dengan garis miring terbalik karena tanda < dan > adalah pengarah keluaran. Tanpa garis miring terbalik, teks yang hendak dibandingkan justru diperlakukan sebagai nama berkas tujuan penulisan. Perbedaan urutan angka dan urutan teks terlihat pada contoh berikut:

bash
# secara angka, 9 lebih kecil daripada 10
test 9 -lt 10
echo $?
# secara teks, "9" justru lebih besar daripada "10"
[ "9" \> "10" ]
echo $?
text Keluaran
0
0

Kedua pemeriksaan bernilai benar sekaligus karena menggunakan ukuran yang berbeda. Secara numerik 9 memang lebih kecil daripada 10, sedangkan secara urutan teks huruf 9 berada setelah huruf 1 sehingga "9" dianggap lebih besar. Kesimpulannya, pilih operator sesuai jenis data yang diperiksa dan jangan mengandalkan intuisi urutan teks untuk angka.

Kurung ganda [[ ]]#

Konstruksi [[ ]] adalah kata kunci bawaan bash, bukan perintah eksternal, dan menawarkan dua kemudahan penting dibanding [ ]. Hasil ekspansi variabel di dalamnya tidak mengalami word splitting maupun perluasan pola nama berkas seperti *.txt, sehingga variabel yang berisi spasi aman ditulis tanpa kutip. Selain itu, [[ ]] menerima operator logika && dan || serta pencocokan pola (pattern matching) pada sisi kanan operator ==.

Perbedaannya terlihat ketika variabel berisi spasi dan kutipnya sengaja dilepas:

bash
# variabel berisi spasi ditulis tanpa kutip pada kedua bentuk
buah="pisang susu"
[ $buah = "pisang susu" ]
echo $?
[[ $buah = "pisang susu" ]]
echo $?
text Keluaran
bash: line 51: [: too many arguments
2
0

Bentuk [ ] menerima empat kata setelah ekspansi sehingga test melaporkan kesalahan dengan pesan too many arguments dan berakhir dengan status 2. Angka pada awal pesan adalah hitungan baris sesi terminal tempat percobaan ini dijalankan. Bentuk [[ ]] menganggap $buah satu kesatuan tanpa memandang spasinya, sehingga perbandingan berjalan dan berakhir dengan nol. Perilaku ini membuat [[ ]] lebih tahan terhadap kelalaian kutip, meskipun kebiasaan mengutip tetap disarankan.

Pencocokan pola pada [[ ]] menggunakan sintaks pola nama berkas, bukan ekspresi reguler:

bash
# pencocokan pola pada sisi kanan ==
ekstensi="tar.gz"
[[ $ekstensi == *.gz ]]
echo $?
[[ $ekstensi == *.zip ]]
echo $?
text Keluaran
0
1

Pola *.gz berarti teks apa pun yang diakhiri .gz, dan pola itu diuji terhadap sisi kirinya secara utuh. Bentuk [ ] tidak memiliki kemampuan ini, dan di situ letak perbedaan fungsional yang paling terasa. Untuk skrip yang harus berjalan di shell mana pun, [ ] tetap menjadi pilihan karena standarnya lebih luas, sedangkan [[ ]] wajar digunakan pada skrip yang shebang-nya sudah menyebut bash.

Kesalahan umum#

  • Menyisakan pembandingan tanpa spasi, misalnya [ "$a"="b" ]. test membacanya sebagai satu kata tunggal sehingga hasilnya selalu benar selama teksnya tidak kosong. Jaga spasi di sekitar [, =, dan ].
  • Menggunakan = untuk angka atau -eq untuk string. Pembandingan silang ini kadang terlihat berhasil pada nilai kecil, tetapi berakhir dengan pesan integer expression expected begitu salah satunya bukan angka.
  • Menulis < atau > di dalam [ ] tanpa garis miring terbalik. bash membacanya sebagai pengarah keluaran sehingga perintah itu membuat berkas baru bernama sesuai operand kanannya, alih-alih membandingkan apa pun.
  • Meletakkan perintah pada baris yang sama dengan then tanpa tanda ;. Struktur if menuntut pemisah antara then dan perintahnya ketika keduanya berada di satu baris.
  • Menutup if dengan done atau esac karena terbawa kebiasaan konstruksi lain. Penutup if adalah fi, dan penutup yang salah berakhir dengan error sintaks unexpected token.

Ringkasan#

  • if bercabang berdasarkan status keluar perintahnya, yaitu nol untuk berhasil, dengan cabang then, elif, else, dan penutup fi.
  • test dan bentuk [ ] melaporkan jawaban benar-salah lewat status keluar, dengan -eq sampai -ge untuk angka, = dan != untuk string, serta -f, -d, dan -e untuk berkas.
  • Perbandingan teks < dan > menilai urutan kamus, bukan besaran angka, dan harus ditulis dengan garis miring terbalik di dalam [ ].
  • [[ ]] adalah kata kunci bash yang tahan terhadap spasi, mendukung && dan ||, serta dapat mencocokkan pola pada sisi kanan ==.

Referensi#