Daftar Isi

Optimisasi Mikro dan Portabilitas dalam Shell-script #6

Shell-scripting mindset shift pt. 6 of 7


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

Strings: printf vs echo

Tak sedikit dari mereka yang menggunakan bashism seperti echo -e, echo -n, dan sebagainya. Walaupun sama sekali bukan masalah jika ditujukan untuk bash/zsh (berdasarkan shebang), tetapi itu kurang tepat jika skrip shell yang ditulis ditujukan untuk POSIX-compliant sh (seperti dash yang paling tegas) di mana echo -e sebenarnya sama dengan echo tanpa opsi sama sekali. POSIX mendefinisikan (setidaknya) hanya opsi -n yang diimplementasikan di echo, tetapi absen di System V. Jika opsi tersebut digunakan maka string tidak diakhiri dengan karakter newline. Selain itu, POSIX mendefinisikan perilaku default echo menginterpretasikan karakter backslash diikuti karakter tertentu akan diinterpretasikan sesuai implementasi shell masing-masing. Misalnya, string \n akan diinterpretasikan sebagai karakter newline ke output. Perintah echo hanya menginterpretasikan argumen sebagai string dan diakhiri dengan karakter newline. Sedangkan perintah printf digunakan untuk lebih dari sekedar string sebab mendukung file format notation.

Shell Escape Sequences

POSIX
(+ekstensi)
GNU BaSH Diinterpretasikan sebagai (atau untuk) …
\a \a Membunyikan peringatan, dinotasikan dengan karakter bell.
\b \b Karakter backspace.
\c \c Menekan output lebih lanjut. Biasa digunakan di akhir argumen.
(tidak ada) \e
\E
Karakter escape. Alternatif gunakan 8-bit oktal \033, 2 digit.
\f \f Karakter form feed.
\n \n Karakter newline.
\r \r Karakter carriage return.
\t \t Karakter horizontal tab.
\v \v Karakter vertical tab.
\\ \\ Karakter backslash.
\0nnn \0nnn Karakter 8-bit bernilai oktal nnn, 0-3 digit.
(tidak ada) \xHH Karakter 8-bit bernilai heksadimal HH, 1-2 digit.
(tidak ada) \uHHHH Karakter unicode bernilai heksadesimal HHHH, 1-4 digit.
(tidak ada) \UHHHHHHHH Karakter unicode bernilai heksadesimal HHHHHHHH, 1-8 digit.

Daftar referensi ANSI escape code ada di sini. Seperti yang dijelaskan di sana, dapat menggunakan \e di bash/zsh atau (sangat disarankan) oktal \033 untuk menginterpretasikan karakter escape.


File Format Notation

Untuk menghindari keambiguan (atau multitafsir) dalam penafsiran Bahasa Inggris (non-sastra) ke Bahasa Indonesia (campuran), penulis menyarankan mengunjungi langsung spesifikasi POSIX di sini.


1
printf '%.7s\n' 'My Last Farewell' # Potong 7 byte string.
/proc/self/fd/1
My Last
1
echo 'My Last Farewell' | cut -b1-7 # Alternatif: `cut`, GNU coreutils.
/proc/self/fd/1
My Last

1
printf '%X\n' "$((50*255/100))" # Kalkulasi 50% alpha, desimal ke heksadesimal.
/proc/self/fd/1
7F
1
echo "ibase=10; obase=16; $((50*255/100))" | bc # POSIX `bc`.
/proc/self/fd/1
7F
1
echo "$(([##16]50*255/100))" # Arithmetic Evaluation, `zsh` 5+.
/proc/self/fd/1
7F

Salah satu trik (favorit penulis) yang jarang diketahui adalah kalkulasi floating-point dengan memanfaatkan notasi format file %f/%F dan memotong byte-nya dengan karakter titik diikuti jumlah byte. Ini perlu pemahaman dengan uji coba ekstra untuk memahaminya. Khusus untuk di bawah, string e-1 menyiratkan 1 digit (dari kanan) angka 77 dalam ekspansi aritmatika, sehingga menginterpretasikan 7.7 dari kalkulasi dengan hasil string 11e-1. Namun, trik ini kurang akurat dan sangat terbatas. Mengapa? Karena bash (dan beberapa shell lain) tidak mendukung kalkulasi floating-point di dalam ekspansi aritmatikanya. Penulis hanya menggunakan trik ini untuk kasus tertentu dengan alasan murni POSIX-compliant shell (tanpa utilitas eksternal yang lain seperti bc).

1
printf '%.16f\n' "$((77/7))e-1" # String `e-1` sebenarnya dipengaruhi 16 bytes.
/proc/self/fd/1
1.1000000000000001
1
echo '7.7/7' | bc -l # POSIX `bc`.
/proc/self/fd/1
1.10000000000000000000
1
echo "$((7.7/7))" # `ksh93`, `zsh`, dan `yash`. Yang lain?
/proc/self/fd/1
1.1000000000000001

Lanjutkan ke Halaman

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