Daftar Isi

Optimisasi Mikro dan Portabilitas dalam Shell-script #4

Shell-scripting mindset shift pt. 4 of 7


بِسْمِ ٱللَّٰهِ ٱلرَّحْمَٰنِ ٱلرَّحِيمِ

Statements: if vs case

Menggunakan if kelihatannya bagus, tetapi jika menginginkan kemungkinan tindakan berbeda untuk diambil, itu cenderung tidak optimal. Di sisi lain, menggunakan case dapat mengoptimalkan pemrosesan seperti ketika membandingkan sebuah string dengan berbagai string lain (atau nilai dari sebuah parameter) sesuai ekspresi pola pencocokan (globbing) yang ditentukan. Sekali cocok atau tidak sama sekali. Hal itu merupakan perbedaan yang menonjol dari konstruksi if dan case.

if Construction

Konstruksi if mengambil tindakan berdasarkan kondisi yang ditentukan, di mana suatu perintah mengembalikan kode/nilai (return code/value) atau exit status. Nilai 0 berarti perintah tersebut benar (true) atau berhasil (success) dieksekusi, selain itu nilai 1 (dan lain-lain yang spesifik seperti 127) merupakan sebuah kesalahan (false) atau kegagalan (failure). Konstruksi if akan melanjutkan untuk mengeksekusi perintah (konsekuensi) yang didefinisikan setelah sintaks then pada kondisi if jika kondisi tersebut bernilai benar. Jika kondisi elif (else if) ditentukan dan perintah pada kondisi if sebelumnya mengalami kesalahan maka konstruksi if akan mengeksekusi perintah (konsekuensi) kondisi elif seperti if, dan jika kondisi else ditentukan maka perintah (konsekuensi) kondisi else akan dieksekusi jika semua kondisi sebelumnya mengalami kesalahan.

1
2
3
4
5
6
7
if [ -e / -a ! -d / ]; then
    echo 'Mustahil untuk mengklaim bahwa / (root) bukan direktori.' >&2
elif [ -e / -a -d / ]; then
    echo 'Benar? Bahwa / (root) termasuk kategori direktori.'
else
    echo 'Error adalah merah, layarmu selalu biru.' >&2
fi
/proc/self/fd/2
Mustahil untuk mengklaim bahwa / (root) bukan direktori.
atau
/proc/self/fd/1
Benar? Bahwa / (root) termasuk kategori direktori.
atau
/proc/self/fd/2
Error adalah merah, layarmu selalu biru.

Konstruksi if biasanya mengandalkan perintah [ (test) dan [[ bawaan untuk menguji apakah sebuah ekspresi (biasanya pathname) adalah file dan sebagainya, atau sebuah parameter nilainya bukan null dan sebaliknya. Menurut penulis, konstruksi if sebenarnya adalah versi estetik (yang elegan) dari operator && (and, double-ampersand) dan || (or, pipe) yang dikelompokkan.

1
2
3
4
5
6
7
{ [ -e / -a ! -d / ] && \
      echo 'Mustahil untuk mengklaim bahwa / (root) bukan direktori.' >&2 \
} || \
{ [ -e / -a -d / ] && \
      echo 'Benar? Bahwa / (root) termasuk kategori direktori.' \
} || \
      echo 'Error adalah merah, layarmu selalu biru.' >&2
/proc/self/fd/2
Mustahil untuk mengklaim bahwa / (root) bukan direktori.
atau
/proc/self/fd/1
Benar? Bahwa / (root) termasuk kategori direktori.
atau
/proc/self/fd/2
Error adalah merah, layarmu selalu biru.

case Construction

Seperti yang sudah dijelaskan di awal, konstruksi case berbeda dengan konstruksi if dalam mengambil tindakan. Konstruksi case hanya sekali mengambil tindakan terhadap string (atau nilai dari sebuah parameter) yang didefinisikan setelah sintaks case, dan membandingkannya dengan berbagai string lain (atau nilai dari sebuah parameter) sesuai ekspresi pola pencocokan (globbing) yang ditentukan. Jika string tersebut cocok maka konstruksi case akan mengeksekusi perintah (konsekuensi) setelah sintaks ekspresi pola pencocokan ) yang ditutup dengan ;; (semicolon). Jika tidak cocok maka konstruksi case akan berakhir dengan exit status 0 seperti konstruksi if.

1
KERN="$(uname -s)"
1
2
3
4
5
6
7
8
case "$KERN" in
    Linux|GNU*|*BSD) echo "Kamu menggunakan sistem operasi ${KERN}."
    ;;
         [Mm]ac*OS*) echo 'Kamu menggunakan sistem operasi 4.3BSD+Mach.'
    ;;
                  *) echo 'Error adalah merah, layarmu selalu biru.' >&2
    ;;
esac
/proc/self/fd/1
Kamu menggunakan sistem operasi Linux.
atau
/proc/self/fd/1
Kamu menggunakan sistem operasi 4.3BSD+Mach.
atau
/proc/self/fd/2
Error adalah merah, layarmu selalu biru.

Dalam setiap kasus, tak sedikit dari mereka menggunakan pola pencocokan untuk menguji atau membandingkan string dengan implementasi konstruksi if secara tidak optimal seperti berikut.

1
2
3
4
5
6
7
if [[ "$KERN" =~ (Linux|GNU.*|.*BSD) ]]; then
    echo "Kamu menggunakan sistem operasi ${KERN}."
elif [[ "$KERN" =~ [Mm]ac.*OS.* ]]; then
    echo 'Kamu menggunakan sistem operasi 4.3BSD+Mach.'
else
    echo 'Error adalah merah, layarmu selalu biru.' >&2
fi
/proc/self/fd/1
Kamu menggunakan sistem operasi Linux.
atau
/proc/self/fd/1
Kamu menggunakan sistem operasi 4.3BSD+Mach.
atau
/proc/self/fd/2
Error adalah merah, layarmu selalu biru.
Apa yang membedakan dari kedua konstruksi tersebut? Sudah jelas bahwa konstruksi if bukan secara eksplisit digunakan sebagai pembanding string yang justru menggunakan perintah lain secara berulang. Dalam konstruksi di atas ialah [[ (untuk pencocokan regular expression) di mana tidak didefiniskan oleh POSIX. Diimplementasikan di ksh. Juga di bash, zsh, yash, dan busybox sh.

Lanjutkan ke Halaman

#1 #2 #3 #4 #5 #6 #7