#!/bin/sh
# Nama file skrip: fungsi.sh
# fungsi add_a_user()...
add_a_user()
{
USER=$1
PASSWORD=$2
shift; shift;
# dua kali shift, sisanya dianggap komentar ...
COMMENTS=$@
echo "Menambahkan pengguna $USER ..."
echo useradd -c "$COMMENTS" $USER
echo passwd $USER $PASSWORD
echo "Pengguna $USER ($COMMENTS) ditambahkan, passwordnya $PASSWORD"
}
# Bagian utama dari skrip berawal di sini
echo "Memulai skrip..."
add_a_user bob letmein Bob Holness the presenter
add_a_user fred badpassword Fred Durst the singer
add_a_user bilko worsepassword Sgt. Bilko the role model
echo "Akhir dari skrip..."
Baris 4 merupakan deklarasi fungsi, diakhiri dengan (). Kemudian diikuti oleh {, dan apapun yang ada sampai ditemukan pasangan } yang sesuai dikatakan sebagai kode atau isi dari fungsi tersebut. Kode ini tidak dieksekusi sampai fungsi tersebut dipanggil. Fungsi siap menerima panggilan. Perlu diketahui bahwa untuk contoh ini, perintah useradd dan passwd didahului dengan echo – ini merupakan teknik debugging yang bermanfaat untuk memeriksa apakah perintah yang tepat akan dieksekusi. Ini juga berarti bahwa anda dapat menjalankan skrip tanpa menjadi root atau menambahkan account pengguna „cerdik‟ ke sistem Linux! Telah diketahui bahwa skrip shell dieksekusi secara sekuensial, runtut. Tidak demikian dengan fungsi. Dalam hal ini, fungsi add_a_user dibaca dan diperiksa sintaksnya tetapi tidak dieksekusi sampai secara eksplisit dipanggil. Eksekusi berawal dengan pernyataan echo "Start of script...". Baris berikutnya, add_a_user bob letmein Bob Holness dikenal sebagai pemanggilan fungsi (function call) sehingga fungsi add_a_user dimasuki dan memulai eksekusi dengan penambahan tertentu ke lingkungan:
$3=Bob
$4=Holness
$5=the
$6=presenter
Sehingga di dalam fungsi tersebut, $1 diset menjadi bob, tidak peduli apa nilai $1 diluar dari fungsi. Sehingga jika kita ingin merujuk $1 "original" di dalam fungsi tersebut, kita harus memberikan suatu nama lain ke $1 – misalnya A=$1 sebelum kita memanggil fungsi. Kemudian, di dalam fungsi, kita dapat mengakses ke $A. Kita menggunakan perintah shift lagi untuk mendapatkan $3 dan seterusnya, semua parameter dalam $@. Fungsi kemudian menambahkan pengguna dan menentukan passwordnya. Skrip meng- echo suatu komentar dan mengembalikan kontrol ke baris berikutnya dari kode utama.
2.2 Lingkup Variabel
Programmer yang telah menggunakan bahasa lain mungkin heran dengan aturan lingkupan fungsi shell. Pada dasarnya, tidak ada batasan lingkupan selain dari parameter ($1, $2, $@, dan lain-lain). Perhatikan potongan kode berikut:
#!/bin/sh
# Nama file skrip: scope.sh
myfunc()
{
echo "Saya telah dipanggil sebagai: $@"
x=2
}
### Skrip utama berawal di sini
echo "Skrip telah dipanggil dengan $@"
x=1
echo "x bernilai $x"
myfunc 1 2 3
echo "x bernilai $x"
Skrip, ketika dipanggil dengan scope.sh a b c memberikan output sebagai berikut:
Skrip telah dipanggil dengan a b c
x bernilai 1
Saya telah dipanggil sebagai: 1 2 3
x bernilai 2
Parameter $@ diubah di dalam fungsi untuk mencerminkan bagaimana fungsi dipanggil. Variabel x, benar-benar efektif sebagai variabel global - myfunc mengubahnya – dan perubahan itu masih efektif ketika kontrol kembali ke skrip utama. Suatu fungsi akan dipanggil dalam sub-shell jika luarannya dipipe ke perintah lain – misalnya "myfunc 1 2 3 | tee out.log" masih akan tetap mengatakan "x adalah 1". Ini adalah karena suatu proses shell baru dipanggil untuk mempipe myfunc(). Ini dapat membuat debugging menjadi sangat sulit. Fungsi tidak dapat mengubah nilai-nilai yang datang bersama dengan pemanggilannya. Salah satu solusinya adalah dengan mengubah nilai dari variabel itu sendiri, bukan parameter yang dilewatkan bersama pemanggilan fungsi. Contoh berikut memberikan penjelasan:
#!/bin/sh
# Nama file skrip:fungsivar.sh
myfunc()
{
echo "\$1 is $1"
echo "\$2 is $2"
# tidak dapat mengubah $1 – jika ditulis:
# 1="Goodbye Cruel"
# maka itu not valid syntax. Caranya: ubah nilai variabel $a:
a="Goodbye Cruel"
}
### Skrip utama bermula di sini
a=Hello
b=World
myfunc $a $b
echo "a is $a"
echo "b is $b"
Kode program di atas mengubah nilai dari variabel $a, sehingga pesan "Hello World" berubah menjadi "Goodbye Cruel World".
2.3 Fungsi Rekursif
Fungsi dapat dibuat bersifat rekursif, memanggil dirinya sendiri. Skrip berikutmemperlihatkan cara menghitung faktorial dari suatu bilangan:
#!/bin/sh
# Nama file skrip: faktorial.sh
# fungsi factorial()
factorial()
{
if [ "$1" -gt "1" ]; then
i=`expr $1 - 1`
j=`factorial $i` #fungsi memanggil dirinya sendiri
k=`expr $1 \* $j`
echo $k
else
echo 1
fi
}
while :
do
echo "Masukkan suatu angka:"
read x
factorial $x #memanggil fungsi factorial()
done
Berikut ini adalah contoh sebuah pustaka atau library sederhana (common.lib) yang selanjutnya dapat dimuat dan diakses oleh suatu skrip shell (fungsi2.sh dan fungsi3.sh). Library biasanya digunakan untuk mendefinisikan fungsi atau variabel umum.
# Nama file skrip: common.lib
# Note no #!/bin/sh as this should not spawn
# an extra shell. It's not the end of the world
# to have one, but clearer not to.
STD_MSG="About to rename some files..."
rename()
{
# expects to be called as: rename .txt .bak
FROM=$1
TO=$2
for i in *$FROM
do
j=`basename $i $FROM`
mv $i ${j}$TO
done
}
#!/bin/sh
# Nama file skrip: fungsi2.sh
# skrip ini memanfaatkan apa
# yang didefinisikan dalam common.lib
. ./common.lib
echo $STD_MSG
rename txt bak
#!/bin/sh
# Nama file skrip: fungsi3.sh
# skrip ini memanfaatkan apa
# yang didefinisikan dalam common.lib
. ./common.lib
echo $STD_MSG
rename html html-bak
Di sini kita melihat dua file skrip mengakses pustaka common.lib, yaitu fungsi2.sh and fungsi3.sh. Keduanya memuat kode sumber common.lib ke dalam dirinya dan menggunakan variabel dan fungsi yang di deklarasikan di dalam file tersebut. Contoh di atas memperlihatkan bagaimana menggunakan ulang kode program dalam pemrograman shell.