Apa tujuan yang dibangun oleh usus besar?

45

Saya telah meretas banyak skrip shell, dan kadang-kadang hal paling sederhana membuat saya bingung. Hari ini saya menemukan skrip yang memanfaatkan :bash builtin (usus besar) secara ekstensif .

The documenation tampaknya cukup sederhana:

: (a colon)  
     : [arguments]  

Jangan lakukan apa pun selain memperluas argumen dan melakukan pengalihan. Status pengembalian adalah nol.

Namun saya sebelumnya hanya melihat ini digunakan dalam demonstrasi ekspansi shell. Kasus penggunaan dalam skrip yang saya temui memanfaatkan struktur ini secara ekstensif:

if [ -f ${file} ]; then
    grep some_string ${file} >> otherfile || :
    grep other_string ${file} >> otherfile || :
fi

Sebenarnya ada ratusan greps, tetapi mereka hanya lebih sama. Tidak ada pengalihan input / output selain struktur sederhana di atas. Tidak ada nilai kembali yang diperiksa kemudian dalam skrip.

Saya membaca ini sebagai konstruksi tidak berguna yang mengatakan "atau tidak melakukan apa-apa". Tujuan apa yang bisa mengakhiri greps ini dengan "atau tidak melakukan apa-apa" melayani? Dalam hal apa konstruksi ini menyebabkan hasil yang berbeda dari hanya meninggalkan || :dari semua contoh?

Caleb
sumber
10
Satu kemungkinan tujuan yang bisa saya lihat adalah untuk digunakan :sebagai alternatif true. Mungkin errexitdiatur dan penulis tidak peduli dengan status keluar dari beberapa perintah.
jw013
halaman tertaut Stackoverflow adalah IMO sedikit lebih komprehensif (sangat bagus untuk membaca halaman ini dan halaman tertaut).
Trevor Boyd Smith

Jawaban:

29

Tampaknya :s dalam skrip Anda digunakan sebagai pengganti true. Jika greptidak menemukan kecocokan dalam file, itu akan mengembalikan kode keluar bukan nol; seperti jw013 menyebutkan dalam komentar, jika errexitdisetel, mungkin oleh -epada baris shebang, skrip akan keluar jika ada yang grepgagal menemukan kecocokan. Jelas, bukan itu yang diinginkan penulis, jadi dia menambahkan || :untuk membuat status keluar dari perintah majemuk tertentu selalu nol, seperti yang lebih umum (dalam pengalaman saya) || true/ || /bin/true.

Kevin
sumber
Duh. Ini dalam konsep skrip pembuatan RPM, dan sementara saya tidak melihat kode keluar memeriksa di dalam skrip, saya lupa untuk mempertimbangkan bahwa proses induk mungkin menonton.
Caleb
8
Jika itu masalahnya, saya akan menyebutnya praktik scripting yang buruk. Secara fungsional ini setara dengan menggunakan truesebagai gantinya, tetapi maksud semantiknya jauh lebih jelas true. :lebih cocok ketika NOP eksplisit diinginkan.
jw013
Dalam pengalaman saya, ini adalah praktik umum dalam skrip RPM. Mungkin tidak seharusnya begitu, tetapi di sanalah kita.
mattdm
beberapa puritan lebih suka :daripada truekarena :merupakan bashbuilt-in di mana seperti truebiasanya biner dikompilasi dengan lebih banyak overhead. biasanya saya menggunakan truekarena kode lebih mudah dibaca (juga saya lebih suka menggunakan sourcedaripada .).
Trevor Boyd Smith
36

The :builtin ini juga berguna dengan Bash "nilai-nilai default assign" ekspansi shell, di mana ekspansi sering digunakan semata-mata untuk efek samping dan nilai diperluas dibuang:

# assign FOO=bar iff FOO is unset
: ${FOO:=bar}
Joni
sumber
2
Datang ke sini mencari ini, bingung ketika saya melihat pola ini dalam skrip untuk mendeklarasikan nilai default.
mencari
21

Saya bisa memikirkan dua tempat yang saya gunakan :di masa lalu.

while :
do
     shell commands
     some exit condition
done

Itu adalah loop selamanya.

function doSomethingStub {
    :
}

Masukkan fungsi rintisan, hanya untuk mendapatkan aliran kontrol tingkat atas yang benar.

Satu penggunaan yang saya lihat di masa lalu: Alih-alih garis #!/bin/sh(atau apa pun), Anda akan melihat :garis. Beberapa kernel Real Unix yang lebih lama atau shell Real Unix akan menggunakan itu untuk berarti "Saya skrip shell, harus menjalankan saya". Seingat saya ini hanya ketika csh membuat terobosan sebagai shell interaktif umum.

Bruce Ediger
sumber
@BruceEdiger: Apakah Anda memiliki referensi ke baris "shecolon"?
l0b0
7
Akhirnya ditemukan referensi dan penjelasan ": di awal naskah": faqs.org/faqs/unix-faq/faq/part3/section-16.html
Bruce Ediger
1
perilaku di awal :sangat aneh. Saya menemukan bahwa itu memang menyebabkan skrip dijalankan sh. di mana seperti ketika Anda memulai skrip tanpa shebang ... ia mencoba untuk menjalankan skrip dengan shell apa pun yang berjalan (jadi jika Anda menjalankannya bashmencoba menjalankannya seolah- basholah Anda memiliki cshmaka mencoba menjalankannya sebagai csh).
Trevor Boyd Smith
19

The :built-in sudah di Thompson shell - itu didokumentasikan untuk Unix V6 pada tahun 1975. Dalam Thompson shell, :menunjukkan label untuk gotoperintah. Jika Anda tidak pernah mencoba menelepon gotosaluran yang diawali , saluran itu adalah komentar yang efektif.

The Bourne shell , nenek moyang kerang Bourne / POSIX seperti yang kita tahu mereka, tidak pernah memiliki gotoyang saya tahu, tapi tetap :sebagai perintah no-op (itu sudah ada dalam Unix V7 ).

Gilles 'SANGAT berhenti menjadi jahat'
sumber
Poin untuk latar belakang sejarah yang informatif.
Tony Barganski
12

Saya menggali referensi lama: "Lingkungan Pemrograman UNIX" (c) 1984 oleh Kernighan dan Pike.

Halaman 147 (Pemrograman Shell) mengatakan ini:

":" adalah perintah built-in shell yang tidak melakukan apa-apa selain mengevaluasi argumennya dan mengembalikan "true". Alih-alih [merujuk pada contoh skrip], kita bisa menggunakan true , yang hanya mengembalikan status keluar yang benar. (Ada juga perintah palsu .) Tetapi ':' lebih efisien daripada benar karena tidak menjalankan perintah dari sistem file . [Italia / penekanan adalah milikku.]

fracjackmac
sumber
2
Tentu saja, truesekarang shell builtin juga pada banyak sistem.
tripleee
8

Saya ingat bahwa versi awal shell tidak memiliki sintaks komentar. Sebuah baris yang dimulai dengan :(yang mungkin akan menjadi executable aktual, mirip dengan /bin/true) akan menjadi alternatif terbaik.

Inilah halaman manual untuk cangkang Thompson kuno (tidak ada hubungan); tidak ada penyebutan sintaks komentar.

Keith Thompson
sumber
4
Asal :sebenarnya adalah indikator label untuk gotoperintah, di beberapa shell kuno (saya tidak tahu yang mana). Label : somethingmemang dapat digunakan sebagai komentar, jika tidak ada yang cocok goto. Latihan itu macet bahkan setelah gotomenghilang.
Gilles 'SO- stop being evil'
8

":" berguna untuk debugging.

DEBUGLOG=": debugfunction"

statement
statement
$DEBUGLOG arg1 arg2 ...
statement
statement

Berjalan secara normal, fungsi debug tidak pernah dieksekusi sehingga ia hanya perlu melangkah di atas noop (variabel dan wildcard diperluas meskipun). Jika diperlukan debugging lebih dalam, hapus noop dari variabel dan fungsi debug dipanggil dengan argumen apa pun yang diperlukan.

Penggunaan praktis lainnya adalah sebagai blok komentar, yang merupakan fitur yang hilang dari sintaksis shell.

: << COMMENT
all --statements --in --here
are now -a here document which are
passed to --the noop
COMMENT
Colin
sumber