Daftar Isi

Optimisasi Mikro dan Portabilitas dalam Shell-script #5

Shell-scripting mindset shift pt. 5 of 7


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

Tests: [ vs [[

Sering kali, kita menjumpai skrip shell (antah-berantah) dengan sintaks yang tidak konsisten. Misalnya, sekian baris menggunakan perintah [ dan sisanya sepenuhnya menggunakan [[, itu terlihat amburadul. Sebagian besar dari mereka tidak mengerti perbedaan fungsi kedua kurung siku tersebut yang sebenarnya (cukup) berbeda. Seperti yang sudah disinggung di pembahasan sebelumnya. Penggunaan konstruksi [[ (di mana fitur spesifik shell tertentu) lebih menawarkan kemampuan ekstra karena peningkatan dari perintah [ (bentuk kedua dari test) bawaan yang didefinisikan oleh POSIX, dan merupakan reserved (key)word sekeluarga konstruksi if dan case.

Shell: built-in vs keyword

Perlu diketahui bahwa sebuah shell mencakup berbagai perintah bawaan dengan variasi sintaks yang berbeda, sehingga berpengaruh pada interpretasi shell tersebut. Mereka dikategorikan sebagai built-in (atau bawaan) dan keyword (atau kata kunci). Sesuai namanya, built-in merupakan sebuah program (atau utilitas) sama seperti program-program berada di /{,usr/}{,s}bin/ yang biasa kita panggil bersama opsi/argumen dengan sintaks terbatas. Mereka juga dapat mengubah pengaturan parameter dari shell itu sendiri. Sebaliknya, keyword diinterpretasikan lebih luas, artinya mereka adalah subunit dari sebuah konstruksi. Maksudnya konstruksi ialah, keyword tidak berfungsi secara mandiri atau memerlukan kelengkapan sintaks seperti membuka dan menutup yang saling melengkapi agar dapat berfungsi, kecuali bentuk kedua test yakni [ harus ditutup dengan ] walau bukan keyword. Gunakan perintah compgen bawaan di bash/zsh untuk menampilkan daftar.

1
compgen -b # Shell built-in.
/proc/self/fd/1

.
:
[
alias
bg
bind
break

[…]

type
typeset
ulimit
umask
unalias
unset
wait

1
compgen -k # Shell (key)word.
/proc/self/fd/1

if
then
else
elif
fi
case
esac

[…]

time
{
}
!
[[
]]
coproc


1
command -V '['
/proc/self/fd/1
[ is a shell builtin
1
command -V '[['
/proc/self/fd/1
[[ is a shell keyword

Equivalent Expressions

[ (test) [[ Uji, apakah target (atau) …
-b file (identik) Merupakan block special file.
-c file (identik) Merupakan character special file.
-d file (identik) Merupakan direktori.
-e file (identik) Merupakan file atau direktori.
-f file (identik) Merupakan file.
-g file (identik) Merupakan file dengan SGID.
-G file (identik) Merupakan file dengan effective group id dari proses sekarang ini.
-h file
-L file
(identik) Merupakan symbolic link. Opsi -L untuk backward compatibility.
-k file (identik) Merupakan file dengan sticky bit.
-O file (identik) Merupakan file dengan effective user id dari proses sekarang ini.
-p file (identik) Merupakan named pipe (FIFO).
-r file (identik) Merupakan file yang dapat dibaca.
-s file (identik) Ukuran file bukan null.
-S file (identik) Merupakan socket.
-t fdx (identik) Merupakan nomor file descriptor yang terbuka dan terhubung.
-u file (identik) Merupakan file dengan SUID.
-w file (identik) Merupakan file yang dapat ditulis, berdasarkan permission bit.
-x file (identik) Merupakan file yang dapat dieksekusi, berdasarkan permission bit.
f1 -nt f2 (identik) File pertama lebih baru dari yang kedua.
f1 -ot f2 (identik) File pertama lebih lama dari yang kedua.
f1 -ef f2 (identik) Keduanya merupakan file yang sama.
-n string (identik) Panjang string bukan null.
-z string (identik) Panjang string adalah null.
s1 = s2 == Kedua string sama dengan. Mendukung globbing di dalam [[.
(tidak ada) =~ Kedua string sama dengan, bedasarkan pola regular expression.
s1 != s2 (identik) Kedua string tidak sama dengan.
s1 \< s2 < String pertama sebelum yang kedua, secara leksikografis.
s1 \> s2 > String pertama sesudah yang kedua, secara leksikografis.
i1 -eq i2 (identik) Kedua integer sama dengan, secara aljabar.
i1 -ne i2 (identik) Kedua integer tidak sama dengan, secara aljabar.
i1 -gt i2 (identik) Integer pertama lebih besar, secara aljabar.
i1 -ge i2 (identik) Integer pertama lebih besar atau sama dengan, secara aljabar.
i1 -lt i2 (identik) Integer pertama lebih kecil, secara aljabar.
i1 -le i2 (identik) Integer pertama lebih kecil atau sama dengan, secara aljabar.
! e (identik) Membalikkan nilai benar atau salah dari exit status ekspresi terkait.
\( e \) ( ) Mengelompokkan berbagai ekspresi, dengan nilai ekspresi akhir .
e1 -a e2 && Eksekusi ekspresi selanjutnya jika ekspresi sebelumnya berhasil.
e1 -o e2 || Eksekusi ekspresi selanjutnya jika ekspresi sebelumnya gagal.

Perlu diperhatikan. Tidak semua shell mengimplementasikan opsi -e, -nt atau -ot atau -ef, dan negasi ! ekspresi. Operator -a dan -o serta pengelompokan ( ekspresi ) hanya digunakan untuk kasus tertentu, dan ditandai sebagai deprecated. Sangat disarankan menggunakan operator && dan || dengan berbagai perintah [, atau gunakan saja [[ jika shell mendukung.

1
SOCKET="${HOME}/.urxvt/urxvtd-localh3art"
1
[ \( -n "$SOCKET" -o ! -z "$SOCKET" \) -a \( -e "$SOCKET" -o -S "$SOCKET" \) ]
1
{ [ "$?" -eq 0 ] || [ ! "$?" -gt 0 ]; } && file "$SOCKET" # { dikelompokkan; }.
/proc/self/fd/1
/home/hacker/.urxvt/urxvtd-localh3art: socket
1
[[ ( -n "$SOCKET" || ! -z "$SOCKET" ) && ( -e "$SOCKET" || -S "$SOCKET" ) ]]
1
[[ "$?" -eq 0 || "$?" -gt '1 / -1' ]] && file "$SOCKET" # Mendukung aritmatika.
/proc/self/fd/1
/home/hacker/.urxvt/urxvtd-localh3art: socket

Perintah test dapat kita manfaatkan untuk variabel internal $_ karena argumen terakhir disimpan.

1
test -t 0 -a -h "/proc/$$/fd/0" && file "${_%%/fd*}/exe"
/proc/self/fd/1
/proc/1337/exe: symbolic link to /bin/dash

Perbedaan yang jarang diketahui adalah bahwa ekspresi di dalam konstruksi [[ dapat befungsi tanpa dikutip tunggal () maupun ganda (") ketika nilai substring (dari sebuah parameter) tersebut mengandung karakter spasi, dan dapat menggunakan pola pencocokan (globbing). Namun, itu tidak berlaku untuk perintah [ karena memang diperlakukan seperti sintaks perintah dengan argumen.

1
QUEEN='Lucy (Kaede)'
1
[ $QUEEN = 'Lucy (Kaede)' ] && echo "$QUEEN"
/proc/self/fd/2
dash: 2: [: Lucy: unexpected operator
1
[[ $QUEEN = [A-Za-z]*\ * ]] && echo "$QUEEN"
/proc/self/fd/1
Lucy (Kaede)

Lanjutkan ke Halaman

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