Fungsi mengelompokkan rangkaian perintah di bawah satu nama sehingga kelompok itu dapat dipanggil berulang kali tanpa disalin ulang. Topik ini membahas cara mendefinisikan fungsi, memberi argumen pada panggilannya, membatasi umur variabelnya dengan local, serta melaporkan hasil lewat kode kembali (exit code). Skrip panjang yang dirapikan menjadi kumpulan fungsi jauh lebih mudah diperiksa dan diperbaiki.
Mendefinisikan fungsi#
Fungsi didefinisikan dengan menulis nama, tanda kurung kosong, lalu badan berisi perintah di antara kurung kurawal. Definisi hanya mendaftarkan fungsi ke shell dan tidak mengeksekusi apa pun, sedangkan eksekusi terjadi setiap kali nama fungsinya dipanggil. Fungsi harus didefinisikan sebelum panggilan pertamanya, karena shell membaca skrip dari atas ke bawah.
#!/bin/bash
# fungsi menghitung luas persegi panjang
hitung_luas() {
local panjang="$1"
local lebar="$2"
echo "Luas: $(( panjang * lebar ))"
}
hitung_luas 4 5
hitung_luas 12 3Luas: 20
Luas: 36Kedua panggilan menggunakan definisi yang sama dengan argumen berbeda, dan itulah manfaat utama fungsi. Kata kunci local membatasi umur variabel panjang dan lebar pada panggilan yang sedang berjalan saja. Tanpa local, penugasan di dalam fungsi menimpa variabel global yang namanya sama, dan kekacauan semacam itu sulit dilacak pada skrip panjang.
Fungsi juga dapat didefinisikan langsung di sesi shell tanpa berkas skrip, dan perilakunya sama persis:
# mendefinisikan fungsi langsung di sesi shell
sapa() {
echo "Halo, $1"
}
sapa "Budi"
sapa "Citra"Halo, Budi
Halo, CitraSetelah definisi ini berjalan, fungsi sapa tetap tersedia sampai sesi berakhir, sehingga dapat dipanggil lagi kapan saja. Pada berkas skrip, definisinya berlaku dari baris definisi sampai akhir berkas. bash juga menerima bentuk function nama, tetapi bentuk nama() lebih umum dan kompatibel dengan shell lain.
Argumen fungsi#
Fungsi menerima argumen seperti skrip menerima argumen, yaitu lewat $1, $2, dan seterusnya, dengan $# menyimpan banyaknya argumen dan "$@" meneruskan seluruhnya. Argumen fungsi berdiri sendiri dan tidak tercampur argumen skrip, karena $1 di dalam fungsi merujuk argumen pertama panggilan fungsi itu, bukan argumen pertama skrip.
Skrip berikut memuat satu fungsi. Seluruh argumen skrip diteruskan ke fungsi itu lewat "$@":
#!/bin/bash
# argumen skrip diteruskan ke fungsi dengan "$@"
sapa_dua() {
echo "Argumen fungsi: $#"
echo "Pertama: $1, kedua: $2"
}
sapa_dua "$@"Argumen fungsi: 0
Pertama: , kedua:Dipanggil tanpa argumen, fungsi menerima nol argumen sehingga penghitungnya nol dan kedua posisinya kosong. Panggilan berikut menyiapkan folder kerja lalu meneruskan dua argumen skrip ke fungsi yang sama:
# folder kerja latihan
mkdir -p /tmp/kerja-fungsi
# menyalin skrip ke folder kerja lalu masuk ke sana
cp luas.sh terus-argumen.sh genap.sh /tmp/kerja-fungsi/
cd /tmp/kerja-fungsi
# argumen skrip diteruskan ke fungsi melalui "$@"
bash terus-argumen.sh Budi CitraArgumen fungsi: 2
Pertama: Budi, kedua: CitraPenghitung berubah menjadi 2 dan kedua posisi terisi, karena "$@" meluas menjadi seluruh argumen pemanggilan sebagai kata-kata terpisah. Apabila penerusannya dilupa, misalnya fungsi dipanggil tanpa "$@", fungsi tetap berjalan tetapi semua posisinya kosong. Kebiasaan menulis sapa_dua "$@" memastikan apa pun yang diberikan ke skrip sampai ke fungsi.
Kode kembali fungsi#
Fungsi melaporkan keberhasilannya lewat kode kembali, yaitu angka yang ditetapkan pernyataan return dengan konvensi nol untuk berhasil dan angka lain untuk gagal. Apabila fungsi berakhir tanpa return, kodenya adalah status perintah terakhir di dalam badannya. Kode kembali inilah yang dibaca oleh if ketika fungsi digunakan sebagai syarat:
#!/bin/bash
# fungsi melaporkan kegenapan lewat kode kembali
genap() {
if [ $(( $1 % 2 )) -eq 0 ]; then
return 0
fi
return 1
}
if genap 10; then
echo "10 genap"
else
echo "10 ganjil"
fi
if genap 7; then
echo "7 genap"
else
echo "7 ganjil"
fi10 genap
7 ganjilFungsi genap menghitung sisa bagi argumennya, lalu memanggil return 0 untuk bilangan genap dan return 1 untuk bilangan ganjil. Struktur if membaca kode tersebut tanpa perlu $?, persis seperti membaca status perintah biasa. Nilai yang sah untuk return adalah nol sampai 255, dan angka di luar rentang itu dibungkus modulo 256, sehingga return 256 justru berakhir dengan status nol. Status fungsi juga dapat dibaca langsung setelah panggilannya:
# status fungsi terbaca lewat $? setelah panggilannya
cek_isi() {
[ -n "$1" ]
}
cek_isi "teks"
echo $?
cek_isi ""
echo $?0
1Fungsi cek_isi tidak menggunakan return sama sekali, sehingga kodenya adalah status perintah terakhirnya, yaitu [ -n "$1" ] yang memeriksa apakah argumennya tidak kosong. Panggilan dengan teks memberi status nol, sedangkan panggilan dengan teks kosong memberi status satu. Pola ini membuat fungsi pemeriksa sederhana dapat ditulis tanpa struktur if di dalamnya.
Menangkap nilai lewat substitusi#
return hanya membawa angka status, bukan nilai hasil perhitungan. Pemisahan ini membuat satu fungsi dapat melaporkan keberhasilan sekaligus mengirim nilainya lewat dua saluran berbeda. Untuk mengambil nilai dari fungsi, cetak nilainya dengan echo, lalu tangkap keluarannya dengan substitusi perintah $():
# nilai hasil perhitungan ditangkap lewat $()
kali() {
echo $(( $1 * $2 ))
}
hasil=$(kali 6 7)
echo "Enam kali tujuh: $hasil"Enam kali tujuh: 42Seluruh keluaran fungsi masuk ke variabel hasil, sehingga pola ini menuntut fungsi mencetak nilai akhirnya saja. Pesan proses, peringatan, atau informasi lain sebaiknya dikirim ke keluaran error agar tidak tercampur ke dalam nilai yang ditangkap. Dengan dua saluran itu, fungsi shell memiliki pasangan yang rapi, yaitu kode kembali untuk keberhasilan dan keluaran standar untuk nilai.
Kesalahan umum#
- Memanggil fungsi sebelum definisinya. Shell membaca skrip berurutan sehingga panggilan di atas definisi berakhir dengan command not found, seolah fungsi itu tidak pernah ada.
- Mengira return mengembalikan nilai seperti pada banyak bahasa pemrograman lain. return hanya menetapkan angka status, sedangkan nilai diambil dari keluaran fungsi lewat
$(). - Melupakan local pada variabel bantu. Penugasan tanpa local menimpa variabel global yang namanya sama, dan efeknya baru terasa jauh dari tempat kesalahannya.
- Menyisipkan echo informasi proses di dalam fungsi yang keluarannya ditangkap
$(). Pesan itu ikut menjadi bagian nilai sehingga hasil tangkapannya tercampur, dan pesan semacam itu sebaiknya dikirim ke keluaran error. - Memakai
$1milik skrip di dalam fungsi tanpa meneruskan argumen. Fungsi memiliki ruang argumennya sendiri, sehingga posisinya tetap kosong sampai dipanggil dengan argumen atau dengan"$@".
Ringkasan#
- Fungsi didefinisikan dengan
nama()diikuti badan di antara kurung kurawal, dan wajib didefinisikan sebelum panggilan pertamanya. - Argumen fungsi menggunakan
$1,$#, dan"$@"yang berdiri sendiri dari argumen skrip, sedangkan local menjaga variabel bantunya tetap lokal. - return menetapkan kode kembali dengan nol untuk berhasil, dan fungsi tanpa return mewarisi status perintah terakhirnya.
- Nilai hasil perhitungan dikirim lewat keluaran standar dan ditangkap dengan substitusi
$().
Referensi#
- Shell Functions — GNU Bash Reference Manual — Sintaks definisi fungsi, argumen posisinya, dan status keluarnya.
- Local Variables — GNU Bash Reference Manual — Perilaku kata kunci local di dalam fungsi.
- bash(1) — Ubuntu manpages — Dokumentasi resmi bash pada Ubuntu 24.04.