Komentar skrip shell multiline - bagaimana cara kerjanya?

92

Baru-baru ini, saya menemukan jenis komentar multiline yang belum pernah saya lihat sebelumnya - ini adalah contoh skrip:

echo a
#
: aaa 
: ddd 
#
echo b

Ini tampaknya berhasil, bahkan vimsintaks-menyoroti itu. Apa sebutan gaya komentar ini dan bagaimana cara menemukan lebih banyak info tentangnya?

Wiesław Herr
sumber
1
Bagaimana jika Anda sebaliknya membungkus kode Anda ke dalam fungsi untuk berkomentar? CommentedOutBlock() { echo "test"; }
Buksy

Jawaban:

135

Itu bukan komentar multi-baris. #adalah komentar satu baris. :(titik dua) bukan komentar sama sekali, melainkan perintah built-in shell yang pada dasarnya adalah NOP , operasi null yang tidak melakukan apa-apa kecuali mengembalikan true, seperti true(dan dengan demikian menetapkan $?ke 0 sebagai efek samping). Namun karena itu adalah perintah, ia dapat menerima argumen, dan karena mengabaikan argumennya, dalam kebanyakan kasus ia bertindak secara dangkal seperti komentar. Masalah utama dengan lumpur ini adalah argumen masih diperluas, yang mengarah ke sejumlah konsekuensi yang tidak diinginkan. Argumen masih dipengaruhi oleh kesalahan sintaksis, pengalihan masih dilakukan sehingga : > fileakan terpotong file, dan : $(dangerous command)substitusi akan tetap berjalan.

Cara yang paling tidak mengejutkan yang sepenuhnya aman untuk memasukkan komentar dalam skrip shell adalah dengan #. Tetap berpegang pada itu bahkan untuk komentar multi-line. Jangan pernah mencoba (ab) menggunakan :komentar. Tidak ada mekanisme komentar multisaluran khusus di shell yang analog dengan /* */bentuk bintang-slash dalam Cbahasa yang mirip.


Demi kelengkapan, tetapi bukan karena itu adalah praktik yang disarankan, saya akan menyebutkan bahwa dimungkinkan untuk menggunakan dokumen-dokumen di sini untuk melakukan "komentar" multi-baris:

: <<'end_long_comment'
This is an abuse of the null command ':' and the here-document syntax
to achieve a "multi-line comment".  According to the POSIX spec linked 
above, if any character in the delimiter word ("end_long_comment" in 
this case) above is quoted, the here-document will not be expanded in 
any way.  This is **critical**, as failing to quote the "end_long_comment" 
will result in the problems with unintended expansions described above. 
All of this text in this here-doc goes to the standard input of :, which 
does nothing with it, hence the effect is like a comment.  There is very 
little point to doing this besides throwing people off.  Just use '#'.
end_long_comment
jw013
sumber
29
+1 sangat penting untuk menjaga tanda kutip tunggal di <<telepon - yang mematikan subtitusi dan ekspansi.
glenn jackman
4
Dan sebagai catatan tambahan, mengisi skrip shell dengan :hal-hal yang seharusnya menjadi komentar akan menyebabkan konsumsi RAM / CPU tambahan. Itu tidak akan penting untuk hal-hal sederhana di desktop Anda, tetapi jika itu sesuatu yang dieksekusi ratusan atau ribuan kali per detik Anda tidak akan melakukan apa-apa, sangat cepat .
bahamat
3
@ Bahahamat: jika Anda menjalankan sesuatu ratusan atau ribuan kali per detik, saya harap Anda tidak akan menuliskannya di shell ... = /
7heo.tk
1
Terkadang, menggunakan utilitas nol untuk beberapa baris teks mungkin berguna. Memulai komentar dengan : <<=cutmemungkinkan untuk menulis POD dalam skrip shell, lihat contoh ini untuk detailnya . Ini memungkinkan untuk digunakan perldoc script.sh. Namun, komentar multi-baris yang ditunjukkan dalam jawaban ini adalah sesuatu yang pasti harus menjadi blok komentar (setiap baris dimulai dengan # ).
basic6
Inilah diskusi yang bagus tentang heredocs, yang digunakan untuk komentar dan kasus penggunaan menarik lainnya (bahkan termasuk pembuatan skrip dynaimc): tldp.org/LDP/abs/html/here-docs.html#EX71C
bguiz
28

Itu bukan gaya berkomentar. yang :built-in command tidak apa-apa; itu disalahgunakan karena berkomentar di sini.

$ help :
:: :
    Null command.

    No effect; the command does nothing.

    Exit Status:
    Always succeeds.
Ignacio Vazquez-Abrams
sumber
25

Pada awalnya, titik dua adalah satu-satunya cara untuk membuat komentar.

Namun, itu bukan komentar yang benar, karena baris diuraikan dengan cara yang persis sama seperti perintah lain diuraikan, dan itu mungkin memiliki efek samping. Sebagai contoh:

: ${a:=x} # assigns the value 'x' to the variable, 'a'

: $(command) # executes 'command'

(Terkadang usus besar digunakan hanya untuk tujuan memunculkan efek samping itu, tetapi kemudian tidak digunakan sebagai komentar.)

Terkadang nyaman menggunakan tanda titik dua untuk mengomentari bagian skrip:

: '
while [ "$n" -ne "$x" ]
do
  : whatever
done
'

Ini adalah penghemat waktu yang hebat dibandingkan dengan mendahului setiap baris #, terutama jika komentar hanya bersifat sementara.

Chris FA Johnson
sumber
2
Metode komentar kutipan tunggal tidak bekerja pada bagian skrip mana pun yang menggunakan kutipan tunggal. Dan jika Anda menggunakan tanda kutip mendekati apa pun yang seharusnya, itu berarti Anda akan memiliki tanda kutip tunggal yang disiramkan di seluruh skrip. Adalah jauh lebih sederhana untuk hanya menggunakan editor yang layak yang memungkinkan Anda melakukan blokir komentar.
jw013
Anda benar bahwa itu hanya akan berfungsi jika tidak ada tanda kutip tunggal di bagian yang dikutip. Namun, skrip tidak perlu memiliki banyak tanda kutip tunggal. Dalam melihat beberapa skrip saya, saya menemukan mereka relatif jarang, dan banyak yang bisa diganti dengan tanda kutip ganda.
Chris FA Johnson
Pilihan kutipan tunggal atau kutipan ganda hampir tidak boleh dipengaruhi oleh sesuatu yang sepele dan tidak relevan karena masalah apakah teks naskah Anda sendiri merupakan string kutipan tunggal yang valid. Kutipan tunggal digunakan untuk mencegah ekspansi, sedangkan tanda kutip ganda memungkinkan ekspansi tertentu dan membutuhkan penguraian tambahan. Ini adalah kriteria nyata untuk menentukan yang akan digunakan.
jw013
Sejauh ini, inilah cara paling cantik untuk melakukannya. Bagus untuk blok dokumentasi kecil. Saya suka lebih baik daripada /* */dan ugh, jangan mulai saya <!-- -->!
alex grey
1

Jika komentar Anda di akhir skrip, Anda dapat melakukannya seperti ini:

#!/bin/sh
echo 'hello world'
exec true
we can put whatever we want here
\'\"\$\`!#%&()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_
abcdefghijklmnopqrstuvwxyz{|}~
Steven Penny
sumber