Apa kegunaan dari perintah: dalam skrip shell, mengingat perintah itu tidak melakukan apa-apa?

27

Dalam jawaban untuk pertanyaan ini tentang komentar dalam skrip shell , diindikasikan bahwa :ini adalah perintah nol yang secara eksplisit tidak melakukan apa-apa (tetapi tidak digunakan untuk komentar).

Apa manfaat dari perintah yang sama sekali tidak melakukan apa pun?

DQdlM
sumber
2
Lihat juga pertanyaan ini yang memiliki jawaban yang lebih baik di sini , yaitu yang :diperlukan untuk menjadi built-in, sementara truetidak, yang mempengaruhi ruang lingkup variabel
Old Pro
2
Secara eksplisit tidak melakukan apa pun dengan anggun .
mikeserv

Jawaban:

19

Saya biasanya menggunakan trueloop; Saya pikir itu lebih jelas:

while true; do
    ...
done

Satu tempat yang saya temukan :sangat berguna adalah pernyataan kasus, jika Anda perlu mencocokkan sesuatu tetapi tidak ingin melakukan apa pun. Sebagai contoh:

case $answer in
    ([Yy]*) : ok ;;
    (*)     echo "stop."; exit 1 ;;
esac
Ilmuwan gila
sumber
3
Saya setuju. trueuntuk suatu kondisi, :untuk NOP.
jw013
1
bash menerima case a in a ) ;; esac. Apakah ada beberapa kerang yang tidak menerima ini?
Kaz
@ Ka: Menurut tata bahasa shell POSIX , case ${var} in value);; *) do_something;; esacdapat diterima. The :perintah tidak diperlukan untuk kasus-kasus yang kosong.
Richard Hansen
12

Awalnya, ini digunakan untuk menentukan bahwa itu adalah program shell Bourne, yang bertentangan dengan program yang dikompilasi C. Ini sebelum shebang dan beberapa bahasa scripting (csh, perl). Anda masih dapat menjalankan skrip dimulai dengan hanya ::

$ echo : > /tmp/xyzzy
$ chmod +x /tmp/xyzzy
$ ./xyzzy

Ini umumnya akan menjalankan skrip terhadap $SHELL(atau /bin/sh).

Sejak itu, penggunaan utama adalah untuk mengevaluasi argumen. Saya masih menggunakan:

: ${EDITOR:=vim}

untuk menetapkan nilai default dalam skrip.

Arcege
sumber
11

: berguna untuk menulis loop yang harus diakhiri dari dalam.

while :
do
    ...stuff...
done

Ini akan berjalan selamanya kecuali breakatau exitdipanggil, atau shell menerima sinyal terminating.

Kyle Jones
sumber
3
Saya merasa bahwa while true; do ...; donemengomunikasikan niat untuk pembaca lebih baik daripadawhile :; do ...; done
Richard Hansen
9

Ketika Anda menginginkan pernyataan "kecuali" dalam skrip shell, Anda bisa menggunakan kondisi "tidak", yang dapat terlihat konyol untuk beberapa tes, atau Anda menggunakan ':' dalam klausa yang benar, dengan kode nyata di false- ayat.

if [ some-exotic-condition ]
then
    :
else
    # Real code here
fi

"Kondisi eksotis" bisa menjadi sesuatu yang tidak ingin Anda abaikan, atau itu hanya jauh lebih jelas jika Anda tidak menggunakan "logika negatif".

Bruce Ediger
sumber
1
Itu juga muncul di skrip yang dihasilkan oleh autoconfkarena lebih mudah untuk menambahkan default :untuk cabang kosong daripada mencari cara untuk membalikkan kondisi.
Dietrich Epp
2
Saya tidak bisa melihat bagaimana menempel di !depan [ some-exotic-condition ]konyol, tapi berlebihan : elsesetelah itu tidak konyol.
Kaz
@ Ka memiliki poin yang bagus. Mari kita ingat bahwa menghadapi kondisi eksotis itu sulit. Jika Anda harus meniadakan semua itu, itu satu hal, tetapi mungkin hanya membuat kondisinya kurang jelas. Apakah '!' meniadakan seluruh kondisi, atau hanya istilah pertama? Terbaik untuk memiliki ':' klausa benar kadang-kadang.
Bruce Ediger
The !Token meniadakan seluruh elemen pipa perintah. while ! grep ... ; do ... done atau if ! [ ... ] ; then ... fi. Ini pada dasarnya eksternal untuk test/[]sintaks. Lihat: pubs.opengroup.org/onlinepubs/9699919799/utilities/…
Kaz
5

Saya hanya pernah menggunakan ini di samping karakter # untuk sementara mengomentari sebuah baris, dalam situasi di mana mengomentari baris menghasilkan kesalahan sintaksis, karena cacat dalam tata bahasa shell tidak memungkinkan urutan perintah kosong :

if condition ; then
    :# temporarily commented out command
fi

Tanpa: kami memiliki urutan perintah yang hilang, yang merupakan kesalahan sintaksis.

Kaz
sumber
4

Ada dua kasus yang menurut saya :berguna:

Tugas variabel default

#!/bin/sh

# set VAR to "default value" if not already set in the environment
: "${VAR=default value}"

# print the value of the VAR variable.  Note that POSIX says the behavior
# of echo is implementation defined if the first argument is '-n' or if any
# argument contains a '\', so use printf instead of echo.
printf '%s\n' "VAR=${VAR}"

Ini adalah cara yang mudah untuk memungkinkan pengguna skrip shell Anda menimpa pengaturan tanpa mengedit skrip. (Namun, argumen baris perintah lebih baik karena Anda tidak menjalankan risiko perilaku tak terduga jika pengguna secara kebetulan memiliki variabel yang Anda gunakan di lingkungan yang diekspor.) Berikut ini cara pengguna akan menimpa pengaturan:

VAR="other value" ./script

The ${VAR=value}sintaks mengatakan untuk set VARke valuejikaVAR belum diatur, kemudian memperluas dengan nilai variabel. Karena kita belum peduli tentang nilai variabel, itu dilewatkan sebagai argumen pada perintah no-op :untuk membuangnya.

Meskipun :perintah no-op, ekspansi dilakukan oleh shell (bukan: perintah!) Sebelum menjalankan :perintah sehingga penugasan variabel tetap terjadi (jika berlaku).

Ini juga dapat diterima untuk menggunakan trueatau perintah lain sebagai gantinya: , tetapi kode menjadi lebih sulit dibaca karena maksudnya kurang jelas.

Skrip berikut juga berfungsi:

#!/bin/sh

# print the value of the VAR variable.  Note that POSIX says the behavior
# of echo is implementation defined if the first argument is '-n' or if any
# argument contains a '\', so use printf instead of echo.
printf '%s\n' "VAR=${VAR=default value}"

Tetapi hal di atas jauh lebih sulit untuk dipertahankan. Jika baris menggunakan ${VAR}ditambahkan di atas printfgaris itu, perluasan tugas default harus dipindahkan. Jika pengembang lupa untuk memindahkan tugas itu, bug diperkenalkan.

Sesuatu untuk dimasukkan ke dalam blok bersyarat kosong

Blok bersyarat kosong umumnya harus dihindari, tetapi kadang-kadang berguna:

if some_condition; then
    # todo:  implement this block of code; for now do nothing.
    # the colon below is a no-op to prevent syntax errors
    :
fi

Beberapa orang berpendapat bahwa memiliki ifblok benar kosong dapat membuat kode lebih mudah dibaca daripada meniadakan tes. Sebagai contoh:

if [ -f foo ] && bar || baz; then
    :
else
    do_something_here
fi

bisa dibilang lebih mudah dibaca daripada:

if ! [ -f foo ] || ! bar && ! baz; then
    do_something_here
fi

Namun saya percaya ada beberapa pendekatan alternatif yang lebih baik daripada blok kosong yang benar:

  1. Masukkan kondisi dalam suatu fungsi:

    exotic_condition() { [ -f foo ] && bar || baz; }
    
    if ! exotic_condition; then
        do_something_here
    fi
  2. Masukkan kondisi di dalam kurung kurawal (atau tanda kurung, tetapi kurung menelurkan proses subkulit dan perubahan apa pun yang dilakukan terhadap lingkungan di dalam subkulit tidak akan terlihat di luar subkulit) sebelum meniadakan:

    if ! { [ -f foo ] && bar || baz; } then
        do_something_here
    fi
  3. Gunakan ||alih-alih if:

    [ -f foo ] && bar || baz || {
        do_something_here
    }

    Saya lebih suka pendekatan ini ketika reaksinya sederhana, seperti menyatakan kondisi:

    log() { printf '%s\n' "$*"; }
    error() { log "ERROR: $*" >&2; }
    fatal() { error "$@"; exit 1; }
    
    [ -f foo ] && bar || baz || fatal "condition not met"
Richard Hansen
sumber
1

Dalam shell pre-bourne lama di UNIX versi kuno, :perintah ini awalnya dimaksudkan untuk menentukan label untuk goto(itu adalah perintah terpisah yang memutar input ke tempat label ditemukan, sehingga label tidak dapat menjadi sintaksis terpisah yang shell tahu tentang. ifjuga merupakan perintah terpisah.) Segera menjadi digunakan untuk komentar, sebelum ada sintaks komentar ( #digunakan untuk backspace) dan hari ini ada sekitar untuk kompatibilitas sebanyak apa pun.

Random832
sumber
0

Selain menggunakannya sebagai pernyataan yang tidak melakukan apa-apa, Anda dapat menggunakannya untuk mengomentari pernyataan tunggal dengan mengubahnya menjadi argumen untuk:.

Martin Stein
sumber
Itu tidak akan persis komentar karena : echo write this line > myfilemasih akan membuat file kosong.
Arcege
5
Sebagaimana dijelaskan dalam link dalam pertanyaan, :adalah TIDAK mekanisme berkomentar yang memadai.
jw013