1 poin oleh GN⁺ 2 jam lalu | 1 komentar | Bagikan ke WhatsApp
  • : di shell adalah perintah null (null command) yang tidak melakukan tindakan apa pun selain mengevaluasi argumen, dan jika digabungkan dengan ekspansi parameter, dapat menangani pemeriksaan argumen wajib dan penetapan nilai default secara ringkas
  • : "${1:?missing argument, aborting!}" akan mencetak pesan diagnostik ke stderr dan keluar dengan status non-nol jika $1 tidak ada atau kosong
  • Jika ${VAR:=default} diberikan sebagai argumen untuk :, ekspansi tetap dijalankan tetapi string hasilnya dibuang, sehingga hanya nilai default yang ditetapkan tanpa menjalankan hasil ekspansi sebagai perintah
  • : juga dapat dimanfaatkan untuk mengosongkan file dan memeriksa apakah file dapat diakses lewat redirection, perintah kosong pada trap, pemeriksaan variabel di lingkungan set -u, serta cabang kondisi yang kosong
  • : "${VAR:=default}" hanya menuliskan nama variabel sekali sehingga mengurangi kemungkinan salah ketik, dan pada while : menjadi kondisi yang selalu sukses untuk mengekspresikan loop tak terbatas

Perintah null dan ekspansi parameter

  • : adalah perintah bawaan perintah null yang mengevaluasi argumen lalu membuang hasilnya
    • Berasal sejak Thompson shell pada 1971; saat itu juga digunakan sebagai label dan penanda komentar pertama di Unix
  • Alih-alih kondisi empat baris, argumen wajib dapat diperiksa dengan satu baris berikut
: "${1:?missing argument, aborting!}"
echo "Hello $1!"
  • Sintaks ekspansi parameter ${name:?diagnostic} memeriksa apakah $name belum disetel atau kosong
    • Jika tidak ada nilai, diagnostic dicetak ke stderr dan shell keluar dengan status non-nol
    • Jika ada nilai, hasilnya sama seperti $name
  • Jika hanya menjalankan ${HELLO:=123} tanpa perintah null, hasil ekspansi 123 dianggap sebagai perintah sehingga terjadi command not found
    • : ${HELLO:=123} mengevaluasi ekspansi, menetapkan HELLO=123, lalu membuang hasilnya
  • Berbeda dengan DATA_DIR="${DATA_DIR:-/var/data}", : "${DATA_DIR:=/var/data}" hanya menuliskan nama variabel sekali, sehingga dapat mengurangi kemungkinan salah ketik seperti DATA_DRI

Cara memanfaatkan :

  • Menetapkan nilai default

    • Menetapkan nilai default variabel sambil membuang hasil ekspansi tanpa menjalankannya
: "${DATA_DIR:=/var/data}"
: "${RETRIES:=3}"
  • Mengosongkan file dan memeriksa akses

    • Jika digabungkan dengan redirection, satu atau beberapa file dapat dikosongkan
: > error.log
: > error.log > access.log
  • Dengan subshell dan redirection, juga dapat memeriksa apakah file dapat dibaca atau ditulis
( : < dataset.json ) && echo YES
( : >> result.json ) && echo YES
  • Tempat yang membutuhkan perintah kosong

    • Dapat digunakan saat secara sintaks membutuhkan perintah seperti trap, tetapi tidak boleh benar-benar melakukan pekerjaan apa pun
trap : INT
sleep 60
  • Juga dapat ditempatkan pada cabang kosong dalam kondisi
if some-command; then
    :
else
    echo "command failed"
fi
  • Memeriksa beberapa variabel

    • Saat set -u aktif, memeriksa sekaligus apakah beberapa variabel sudah disetel
set -u
: "$DEPLOY_ENV" "$HOST"
  • Loop tak terbatas

    • Karena : adalah kondisi yang selalu sukses, loop tak terbatas dapat ditulis secara ringkas
while :; do
  echo "I love colons"
  sleep 1
done

1 komentar

 
GN⁺ 2 jam lalu
Komentar Lobste.rs
  • Jika prompt disusun seperti berikut, bahkan saat seluruh baris disalin-tempel, bagian prompt akan diabaikan dan hanya perintahnya yang dijalankan
    : hayalci@tassadar ~/src/dool ; jj rebase -s dxw -d mrn
    • Terinspirasi dari Plan 9, juga memakai opsi autocd shell dan format berikut
      ~/directoryname; <command>
      Setiap kali menyalin baris perintah shell, shell akan terus melakukan cd ke direktori tempat perintah itu semula dijalankan
    • Di zsh, bisa diatur agar menempelkan spasi tak terlihat tanpa line break menghapus isi di sebelah kiri
      nbsp=$'\u00A0'  
      PS1="...$nbsp"  
      bindkey -s $nbsp '^u'  
      
  • Di Makefile, tanda titik dua sering dipakai untuk output yang lebih rapi
    out/%.o: src/%.c  
        @echo CC $@  
        @$(CC) -c -o $@ $<  
    
    Dengan cara ini, make bisa menjalankan beberapa proses echo sekaligus dan menulis ke stream yang sama sehingga saling mengganggu. Jika diubah seperti berikut, yang melakukan output bukan proses anak melainkan proses make itu sendiri
    out/%.o: src/%.c  
        : CC $@  
        @$(CC) -c -o $@ $<  
    
  • Pernah melihat teknik ini di skrip shell, tetapi sulit menemukan dokumentasi yang berguna lewat man : atau whatis :
    Mirip dengan perintah true, tetapi bedanya tidak bereaksi khusus terhadap --help, --version, dan semacamnya, serta jumlah karakternya lebih sedikit
    • Untuk perintah bawaan Bash, sebaiknya cari dengan help, bukan man
      $ help :  
      :: :  
          Null command.
      
          No effect; the command does nothing.
      
          Exit Status:  
          Always succeeds.  
      
    • Di Fish, : secara harfiah adalah alias dari true
  • Ekspansi parameter tetap terjadi tanpa titik dua, jadi muncul pertanyaan kenapa null command tetap diperlukan
    • Ekspansi parameter memang tetap terjadi, tetapi tanpa sintaks yang mengonsumsi hasilnya seperti null command, shell akan menganggap string yang sudah diekspansi sebagai perintah yang harus dijalankan. Penjelasan ini juga ditambahkan ke FAQ
      % ${HELLO:=123}  
      zsh: command not found: 123  
      
      % : ${HELLO:=123}  
      % echo $HELLO  
      123  
      
    • Hasil string yang diinterpolasi ditafsirkan sebagai perintah yang akan dijalankan
      #!/bin/sh  
      "${1:?missing argument, aborting!}"  
      
      $ sh foo.sh sh  
      sh-5.3$  
      
  • Saat sedang mengetik perintah dan ingin menjalankannya lagi nanti, tambahkan titik dua di awal baris agar tersimpan di riwayat eksekusi. Nanti cukup cari baris itu di riwayat dan hapus huruf pertamanya untuk benar-benar menjalankannya
    Namun, belum terpikir untuk memanfaatkannya pada efek samping yang muncul saat argumen dievaluasi
    • Selain :, bisa juga diawali # untuk menyimpannya sebagai komentar. Jika itu sesuatu yang akan dijalankan nanti, kelebihannya adalah ekspresi di dalamnya tidak dievaluasi lebih dulu
    • Di zsh, dengan Meta-q atau Alt-q, baris saat ini bisa disingkirkan sementara, menjalankan perintah lain, lalu setelah selesai baris semula dikembalikan ke buffer baris perintah
      https://nathangrigg.com/2014/04/zsh-push-line-or-edit/
  • Di macOS masih memakai Bash 3, dan muncul error berikut
    -bash: !}": event not found
    • Penasaran apakah ini akan berfungsi jika penggunaan "!" dihapus
  • Kode berikut di Con-colon-sion berpotensi lebih membingungkan orang daripada while true; do...
    while : colons are more than punctuation; do  
      echo "I love colons"  
      sleep 1  
    done  
    
    while true; do hanya lebih panjang tiga karakter daripada while :; do, jadi sudah cukup singkat, dan kode itu tampaknya bukan contoh yang cocok untuk menyampaikan poin yang ingin dijelaskan penulis
    • Itu bukan contoh yang harus diikuti apa adanya, melainkan permainan kata. Jika bisa memahami kode itu, berarti sudah tahu null command, dan titik dua memang benar punya makna lebih dari sekadar tanda baca
    • Yang semula ingin ditunjukkan tampaknya adalah loop tak berujung seperti berikut, tetapi demi terlihat keren malah jadi meleset dari intinya
      while :; do  
          something  
      done