Kamis, 13 Desember 2012

Modul 3


Perulangan dan Seleksi

Sebagian besar bahasa pemrograman mempunyai konsep perulangan atau loop. Jika kita
perlu mengulangi suatu tugas sebanyak 20 kali, kita tidak harus menuliskan kode yang
sama sebanyak 20 kali. Shell Bash menyediakan perulangan for dan while. Shell Linux
memang menyediakan lebih sedikit fitur dibandingkan bahasa dunia C/C++. 
Perulangan For
Perulangan for digunakan untuk melakukan pekerjaan berulang sebanyak daftar yang
disediakan: 
#!/bin/sh
# Nama file skrip: for1.sh
for i in 1 2 3 4 5 
do
echo "Looping ... number $i" 
done 
Coba eksekusi dan perhatikan hasil yang diperoleh. Program di atas meminta shell
mengeksekusi perintah-perintah di dalam blok  do...done sebanyak jumlah elemen di
dalam daftar setelah in, yaitu 5 (1, 2, 3, 4, 5). 
Penulisan elemen dari daftar juga dapat berbentuk seperti pada contoh di bawah ini: 
#!/bin/sh
# Nama file skrip: for2.sh
for i in hello 1 * 2 goodbye
do 
echo "Looping ... i is set to $i"
done 

Pastikan bahwa anda memahami apa yang terjadi di sini. Coba hilangkan tanda *  dan ulangi lagi dengan kembali menyertakan *. Anda tentu tahu apa yang dihasilkan saat eksekusi. Coba jalankan skrip di atas dari dalam direktori lain. Coba apit * dengan tanda petik
ganda, menjadi “*”. Bagaimana jika * didahului backslash (\*) ? Skrip pertama (for1.sh) memberikan hasil eksekusi berikut: 
Looping .....  number 1
Looping .....  number 2
Looping .....  number 3
Looping .....  number 4
Looping .....  number 5

Sedangkan skrip kedua (for2.sh) menunjukka hasil ekskusi berikut: 
Looping ... i is set to hello
Looping ... i is set to 1 
Looping ... i is set to (nama dari file pertama dalam direktori aktif)
 ... dan seterusnya ...
Looping ... i is set to (nama dari file terakhir dalam direktori aktif)
Looping ... i is set to 2 
Looping ... i is set to goodbye

Seperti terlihat, for melakukan perulangan sebanyak input yang diberikan kepadanya, dari input pertama sampai terakhir. 
Perulangan While
Perulangan while dapat digunakan untuk melakukan pekerjaan berulang yang jumlah
perulangannya tidak pasti tetapi bergantung pada suatu kondisi yang harus dipenuhi.
Perhatikan skrip berikut: 
#!/bin/sh
# Nama file skrip: while.sh
INPUT_STRING=hello
while [ "$INPUT_STRING" != "bye" ]
do 
echo "Ketikkan sesuatu (bye untuk keluar)"
read INPUT_STRING 
echo "Anda mengetikkan: $INPUT_STRING"
done 
Apa yang terjadi di sini? Pernyataan echo dan read akan dijalankan secara terus menerus
sampai anda mengetikan "bye". Mengapa variabel INPUT_STRING  diberi nilai awal
“hello”? 
Simbol titik-dua (:) selalu bernilai true; ini dapat digunakan pada waktu tertentu. Skrip di
bawah ini menunjukkan cara keluar program yang lebih elegan dari sebelunnya. 
#!/bin/sh
# Nama file skrip: while2.sh
while :
do 
echo "Ketikkan sesuatu (^C untuk keluar)"
read INPUT_STRING 
echo "Anda mengetikkan: $INPUT_STRING"
done 

Shell menyediakan while berbentuk while  read  f. Contoh di bawah ini menggunakan pernyataan case yang akan dihabas pada bagian lain panduan ini. Skrip ini membaca dari file  myfile,  dan  untuk  setiap  baris,  memberitahukan  pengguna  bahasa  apa  yang digunakan. Setiap baris harus diakhiri dengan LF (baris baru) - jika cat  myfile tidak berakhir dengan suatu baris blank (kosong) maka baris terakhir tersebut tidak akan diproses. 
#!/bin/sh
# Nama file skrip: while3a.sh
while read f
do 
case $f in
hello) 
howdy)
gday)
bonjour)
"guten tag")
"apa kabar")
*)
;;
esac 
done < myfile
echo English ;;
echo American ;;
echo Australian ;;
echo French ;;
echo German ;;
echo Indonesian ;;
echo Unknown Language: $f 
Pada banyak sistem Linux, ini dapat pula dilakukan dengan:
#!/bin/sh
# Nama file skrip: while3b.sh
while f=`line` 
do
.. proses f .. 
done < myfile

Karena while  read  f bekerja hanya dengan Linux dan tidak bergantung pada program eksternal  line  maka  bentuk  pada  while3a.sh  lebih  disukai.  Mengapa  metode  ini menggunakan backtick (`)? 
Banyak programmer lebih menyukai $i (bukan $f)  sebagai default untuk perulangan. Berikut ini adalah contoh eksekusi dari skrip while3a.sh: 
$ i=THIS_IS_A_BUG
$ export i
$ ./while3a.sh something 
Unknown Language: THIS_IS_A_BUG 
Hindari kesalahan ketik. Lebih baik menggunakan ${x}, bukan hanya $x. Jika x="A" dan anda ingin mengatakan "A1" maka anda perlu echo ${x}1, sedangkan echo $x1 akan  mencoba mengakses variabel x1 yang sebenarnya tidak ada.
Ada hal yang sangat menarik pada shell Bash. Pembuatan banyak direktori dengan nama  hampir sama dapat dilakukan dengan mudah. Misalnya membuat 8 direktori berawalan “rc” kemudian dilanjutkan suatu angka atau huruf dan diakhir dengan “.d”, dapat ditulis: 
mkdir rc{0,1,2,3,4,5,6,S}.d 
lebih sederhana dari pada anda menulis: 
for runlevel in 0 1 2 3 4 5 6 S
do 
mkdir rc${runlevel}.d
done 
Perhatikan cara rekursif penggunaan perintah ls berikut. Kita dapat menampilkan daftar file dari banyak direktori sekaligus. 
$ cd /
$ ls -ld {,usr,usr/local}/{bin,sbin,lib}
drwxr-xr-x 2 root root 4096 Oct 26 01:00 /bin
drwxr-xr-x 6 root root 4096 Jan 16 17:09 /lib
drwxr-xr-x 2 root root 4096 Oct 27 00:02 /sbin
drwxr-xr-x 2 root root 40960 Jan 16 19:35 usr/bin
drwxr-xr-x 83 root root 49152 Jan 16 17:23 usr/lib
drwxr-xr-x 2 root root 4096 Jan 16 22:22 usr/local/bin
drwxr-xr-x 3 root root 4096 Jan 16 19:17 usr/local/lib
drwxr-xr-x 2 root root 4096 Dec 28 00:44 usr/local/sbin
drwxr-xr-x 2 root root 8192 Dec 27 02:10 usr/sbin
Perulangan  while  sering  digunakan  bersama  dengan  seleksi  kondisi  memanfaatkan perintah test dan case
III.2 Seleksi Kondisi
Test
Test digunakan secara virtual oleh setiap  skrip shell yang ditulis. Test memang tidak sering dipanggil secara langsung. Test sering dipanggil sebagai [. [ adalah link simbolik ke perintah test, membuat program shell lebih nyaman dibaca. 
Coba tulis perintah di bawah ini dan perhatikan luarannya: 
$ type [
[ is a shell builtin 
$ which [
/usr/bin/[ 
$ ls -l /usr/bin/[
lrwxrwxrwx 1 root root 4 Mar 27 2000 /usr/bin/[ -> test 
Ini berarti bahwa '[' sebenarnya adalah sebuah program yang sudah built-in seperti ls. Karena termasuk perintah maka saat penggunaan ‘[‘ harus diberi jarak (spasi) saat digunakan bersama string atau perintah lain.  Seleksi kondisi seperti ini: 
if [$foo == "bar" ] tidak akan bekerja. Baris tersebut diterjemahkan sebagai if  test$foo  ==  "bar"  ], dimana terdapat ']' tanpa '[' permulaan. Letakkan spasi di awal dan akhir semua operator.
Jika  anda  menjumpai  kata ‘SPACE’  di  dalam  panduan  ini,  berarti  anda  diminta menggatinya dengan spasi. Jika tidak ada spasi maka skrip shell tidak bekerja: 
if SPACE [ SPACE "$foo" SPACE == SPACE "bar" SPACE ] 
Test merupakan tool perbandingan yang sederhana tetapi powerful. Gunakan perintah man test untuk mengetahui manual lengkap dari perintah test. 
Test sering dipanggil secara tak langsung melalui pernyataan if dan while. Sintaks untuk if...then...else... adalah 
if [ ... ]
then 
# if-code
else 
# else-code
fi 
Pernyataan fi merupakan kebalikan dari if. Bentuk seperti ini juga digunakan pada case dan esac. Anda juga perlu waspadai sintaks - perintah "if  [  ...  ]" dan "then" harus pada baris-baris berbeda. Sebagai alternatif, titik-koma ";" dapat digunakan untuk memisahkannya: 
if [ ... ]; then
# lakukan sesuatu 
fi
Anda juga dapat menggunakan elif, seperti ini:
if [ something ]; then
echo "Something" 
elif [ something_else ]; then
 echo "Something else" 
else
echo "None of the above"
fi

Skrip di atas akan meng-echo "Something" jika test terhadap [  something  ] berhasil, jika tidak maka dilakukan test terhadap [  something_else  ] dan memroses echo "Something else" jika berhasil. Jika semuanya gagal, maka akan menjalankan echo "None of the above".  Coba praktekkan potongan kode berikut. Sebelum menjalankannya set variabel X untuk beberapa nilai (coba -1, 0, 1, hello, bye, dan lain-lain). Anda dapat melakukan ini sebagai
berikut: 
$ X=5
$ export X
$ ./test.sh 
... output of test.sh ... $
X=hello 
$ ./test.sh
... output of test.sh ... $
X=test.sh
$ ./test.sh 
... output of test.sh ...

Kemudian coba lagi, dengan $X sebagai nama dari file yang ada, misalnya /etc/hosts
#!/bin/sh
# Nama file skrip: test.sh
if [ "$X" -lt "0" ]
then 
echo "X is less than zero"
fi
if [ "$X" -gt "0" ]; then 
echo "X is more than zero"
fi 
[ "$X" -le "0" ] && \
echo "X is less than or equal to  zero" [
"$X" -ge "0" ] && \
echo "X is more than or equal to zero" [
"$X" = "0" ] && \
echo "X is the string or number \"0\"" [
"$X" = "hello" ] && \
echo "X matches the string \"hello\"" [
"$X" != "hello" ] && \
echo "X is not the string \"hello\"" [
-n "$X" ] && \
echo "X is of nonzero length" 
[ -f "$X" ] && \
echo "X is the path of a real file" || \
echo "No such file: $X" 
[ -x "$X" ] && \
echo "X is the path of an executable file" [
"$X" -nt "/etc/passwd" ] && \
echo "X is a file which is newer than /etc/passwd" 
Perlu diketahui bahwa kita dapat menggunakan titik-koma (;)  untuk menggabungkan dua baris (menjadi satu baris). Ini sering dilakukan untuk menghemat ruang dalam pernyataan if yang sederhana. Karakter backslash memberitahukan shell bahwa ini bukanlah akhir baris, tetapi dua atau lebih baris agar diperlakukankan sebagai satu baris. Ini berguna untuk memudahkan pembacaan kode.  Biasanya baris berikutnya diinden (agak masuk ke dalam). 
Perintah test dapat mengerjakan banyak pengujian terhadap bilangan, string dan nama file.  Perlu diketahui bahwa parameter -a, -e (berarti "file exists"), -S (file is a Socket), -nt (file is newer than), -ot (file is older than), -ef (paths refer to the same file) dan -O (file is owned my user) tidak tersedia pada shell Bash lama (seperti /bin/sh pada Solaris, AIX, HPUX, dan lain-lain). 
Ada cara yang lebih mudah dalam menuliskan pernyataan if: Perintah && dan ||
menyebabkan kode tertentu dijalankan jika test bernilai True. 
#!/bin/bash
[ $X -ne 0 ] && echo "X isn't zero" || echo "X is zero" 
[ -f $X ] && echo "X is a file" || echo "X is not a file" [
-n $X ] && echo "X is of non-zero length" || \
 echo "X is of zero length" 
Perlu dicatat bahwa ketika anda mengubah nilai X ke suatu nilai non-numerik, beberapa perbandingan awal memberikan pesan berikut: 
test.sh: [: integer expression expected before -lt
test.sh: [: integer expression expected before -gt
test.sh: [: integer expression expected before -le
test.sh: [: integer expression expected before -ge 
Ini karena -lt, -gt, -le, -ge adalah perbandingan dirancang hanya untuk integer dan tidak berjalan terhadap string. Perbandingan string seperti != akan memperlakukan "5" sebagai suatu string, tetapi tidak dapat memperlakukan "Hello" sebagai suatu integer, sehingga perbandingan integer bermasalah. Jika anda ingin skrip shell berjalan lebih baik, maka periksa terlebih dahulu isi variabel sebelum dilakukan test - mungkin menjadi seperti ini: 
echo -en "Please guess the magic number: "
read X
echo $X | grep "[^0-9]" > /dev/null 2>&1
if [ "$?" -eq "0" ]; then
# If the grep found something other than 0-9 #
then it's not an integer.
echo "Sorry, wanted a number" 
else
# The grep found only 0-9, so it's an integer. #
We can safely do a test on it. 
if [ "$X" == "7" ]; then
echo "You entered the magic number!" 
fi
fi 
Pada cara ini anda dapat meng-echo pesan yang lebih bermakna kepada pengguna dan keluar (exit).  Variabel $? akan dijelaskan pada bagian lain panduan ini dan perintah grep perlu dipelajari lebih lanjut. Perintah grep [0-9] mencari baris teks yang mengandung digit (0-9). Tanda caret (^) dalam grep  [^0-9] hanya akan mencari baris yang hanya  tidak mengandung bilangan. Apa yang dihasilkan perintah grep -v [0-9]? Perintah test dapat digunakan dalam perulangan while. Contohnya adalah: 
#!/bin/sh
# Nama file skrip: test2.sh
X=0 
while [ -n "$X" ]
do 
echo "Masukkan teks (ENTER untuk keluar)"
read X
echo "Anda menulis: $X" 
done 
Kode ini akan terus meminta input sampai anda menekan ENTER (X panjangnya nol). Bagaimana jika while [ -n  "$X" ]  diganti dengan  while [ -n $X ], dengan menghilangkan dua tanda petik gandanya? Perhatikan eksekusi di bawah ini: 
$ ./test2.sh
Masukkan teks (ENTER untuk keluar)
fred 
Anda menulis: fred
Masukkan teks (ENTER untuk keluar)
wilma 
Anda menulis: wilma
Masukkan teks (ENTER untuk keluar)
Anda menulis: 
Kode di atas dapat dibuat lebih rapi dengan menyertakan test di dalam loop: 
#!/bin/sh
# Nama file skrip: test3.sh
X=0 
while [ -n "$X" ]
do 
echo "Enter Masukkan teks (ENTER untuk keluar)"
read X 
if [ -n "$X" ]; then
echo " Anda menulis: $X" 
fi
done 
Anda telah menggunakan dua sintaks berbeda untuk pernyataan if di atas, yaitu: 
if [ "$X" -lt "0" ]
then 
echo "X lebih kecil daripada nol"
fi
..........  dan ..........  
if [ ! -n "$X" ]; then
 echo "You said: $X" fi   
Case
Pernyataan case menghemat pernyataan if .. then .. else banyak baris. Sintaksnya
sangat sederhana:
#!/bin/sh
# Nama file skrip: talk.sh 
echo "Please talk to me ..."
while : 
do
read INPUT_STRING
case $INPUT_STRING in
 hello) 
esac
done
echo 
echo "Hello yourself!"
;; 
bye)
echo "See you again!" 
break
;; 
*)
echo "Sorry, I don't understand"
;; 
echo "That's all folks!"
Coba jalankan kode di atas dan perhatikan bagaimana kerjanya... 
$ ./talk.sh
Please talk to me ... 
hello
Hello yourself!
What do you think of politics? 
Sorry, I don't understand
bye 
See you again!
That's all folks! 
Baris case sendiri selalu berformat sama. Dimulai dengan memeriksa nilai suatu variable kondisi, pada contoh di atas adalah variabel INPUT_STRING
Pilihan-pilihan kemudian didaftarkan dan diikuti oleh suatu kurung tutup seperti  hello) dan  bye). Ini berarti bahwa jika INPUT_STRING cocok dengan hello maka bagian kode itu dieksekusi, sampai dengan dua titik-koma. Jika INPUT_STRING cocok dengan bye maka pesan “goodbye” dicetak dan keluar dari perulangan. Jika anda ingin  keluar dari skrip maka dapat menggunakan perintah exit, bukan break.  Pilihan ketiga, di sini *), merupakan kondisi catch-all default; tidak harus tetapi sering berguna untuk tujuan debugging bahkan jika kita  mengetahui nilai apa yang akan dimiliki variabel dalam test.  Pernyataan case lengkap diakhiri dengan esac dan loop while diakhiri dengan done


Contoh skrip untuk memeriksa kesalahan username dari sistem Linux! Penguna memberikan inputan dari keyboard (gunakan perintah read)





Tidak ada komentar:

Posting Komentar