Saya menulis skrip ini:
#!/bin/bash
while [ true ]
do
currentoutput="$(lsusb)"
if [ "$currentoutput" != "$lastoutput" ]
then
echo "" date and Time >> test.log
date +%x_r >> test.log
lastoutput="$(lsusb)"
lsusb >> test.log
fi
sleep 5
done
Saya seorang pemula yang mencoba belajar dengan cepat dan saya mendapat pertanyaan tentang tanda kutip variabel .
Letakkan variabel antara $ (), saya mengerti, tetapi mengapa tanda kutip dibutuhkan bahkan dalam if
pernyataan? Apakah itu untuk membuat perintah bersarang?
while [ true ]
memang menghasilkan loop tak terbatas, tetapi mungkin bukan karena alasan yang Anda pikirkan;while [ false ]
juga menghasilkan loop tak terbatas, karena dengan argumen tunggal,[ ... ]
berhasil jika argumen itu adalah string yang tidak kosong.while true
akan benar - benar menjalankan perintah bernamatrue
(yang selalu berhasil).$()
. Anda menaruh perintah di dalam$()
.Jawaban:
Tanda kutip mencegah "pemisahan kata". Yaitu: memecah variabel menjadi beberapa item pada karakter spasi putih (atau lebih tepatnya, pada spasi, tab, dan baris baru seperti yang didefinisikan dalam nilai
$IFS
variabel shell default ).Sebagai contoh,
Di sini kita mendefinisikan
howmany
fungsi yang hanya memberi tahu kita berapa banyak parameter posisi yang diberikan. Seperti yang Anda lihat, ada dua item yang diteruskan ke variabel, dan dengan tanda kutip teks dalam variabel diperlakukan sebagai satu unit.Ini penting untuk memberikan informasi yang akurat. Misalnya, jika variabel berisi path ke file, dan nama file berisi spasi di mana saja di path, perintah yang Anda coba jalankan mungkin gagal atau memberikan hasil yang tidak akurat. Jika kami mencoba membuat file dengan
$var
variabel,touch $var
akan membuat dua file, tetapitouch "$var"
hanya satu.Sama halnya dengan Anda
[ "$currentoutput" != "$lastoutput" ]
. Tes khusus ini melakukan perbandingan pada dua string. Ketika tes berjalan,[
perintah harus melihat 3 argumen - string teks,!=
operator, dan string teks lainnya. Mempertahankan tanda kutip ganda mencegah pemisahan kata, dan[
perintah melihat dengan tepat 3 argumen itu. Sekarang apa yang terjadi jika variabel tidak dikutip?Di sini, pemisahan kata terjadi, dan sebagai gantinya
[
melihat dua stringhello
danworld
diikuti oleh!=
, diikuti oleh dua string lainnyahi world
. Poin utamanya adalah bahwa tanpa tanda kutip ganda, isi variabel dipahami sebagai unit yang terpisah dan bukan satu item keseluruhan.Menetapkan substitusi perintah tidak memerlukan tanda kutip ganda seperti pada
di mana Anda memiliki
df
output perintah disimpanvar
. Namun, merupakan kebiasaan yang baik untuk selalu menggandakan variabel kutipan dan memerintahkan substitusi$(...)
kecuali Anda memang menginginkan output diperlakukan sebagai item terpisah.Di samping catatan,
bagian bisa
[
adalah perintah yang mengevaluasi argumennya, dan[ whatever ]
selalu benar terlepas dari apa yang ada di dalamnya. Sebaliknya,while true
gunakan perintahtrue
yang selalu mengembalikan status keluar sukses (dan itulah yangwhile
dibutuhkan loop). Perbedaannya sedikit lebih jelas dan sedikit pengujian yang dilakukan. Atau, Anda juga bisa menggunakan:
bukannyatrue
Kutipan ganda
echo "" date and Time
sebagian mungkin dapat dihapus. Mereka hanya memasukkan string kosong dan menambahkan ruang ekstra ke output. Jika itu diinginkan, jangan ragu untuk menyimpannya di sana, tetapi tidak ada nilai fungsional tertentu dalam kasus ini.Bagian ini mungkin bisa diganti dengan
echo "$currentoutput" >> test.log
. Tidak ada alasan untuk menjalankanlsusb
lagi setelah dijalankancurrentoutput=$(lsusb)
. Dalam kasus di mana trailing baris baru harus dipertahankan dalam output - orang bisa melihat nilai dalam menjalankan perintah beberapa kali, tetapi dalam kasuslsusb
tidak perlu untuk itu. Semakin sedikit perintah eksternal yang Anda panggil, semakin baik, karena setiap panggilan ke perintah non-built-in menimbulkan biaya dalam CPU, penggunaan memori, dan waktu eksekusi (meskipun perintah mungkin sudah dimuat sebelumnya dari memori).Lihat juga:
sumber
bash
. Tetapi pada bagian terakhir tidak seharusnyaecho "$currentoutput" >> test.log
lebih baikprintf '%s\n' "$currentoutput" >> test.log
?printf
harus dipilih untuk portabilitas. Karena kami menggunakan skrip khusus-bash di sini, itu dapat dimaafkan untuk digunakanecho
. Tetapi pengamatan Anda sangat benarecho
sepenuhnya dapat diandalkan bahkan ketika shell dikenal sebagai bash (dan nilaixpg_echo
danposix
bendera diketahui); jika nilai Anda bisa-n
atau-e
, itu bisa hilang alih-alih dicetak.Dalam
currentoutput="$(lsusb)"
lsusb bukan variabel, itu adalah perintah. Apa yang dilakukan pernyataan ini, menjalankanlsusb
perintah dan memberikan outputnya kecurrentoutput
variabel.Sintaks yang lebih lama untuk ini adalah
Anda dapat menemukannya di banyak contoh dan skrip
Untuk menjawab bagian lain dari pertanyaan Anda,
if [ ]
bagaimana sintaks untukif
didefinisikan dalam bash. Lihat lainnya di https://www.tldp.org/LDP/Bash-Beginners-Guide/html/sect_07_01.htmlsumber
[ ]
itu sebenarnyatest
perintah. Anda dapat menggunakanif
pernyataan dengan perintah lain juga, karena itu bergantung pada tes 0 atau tidak nol dari kode keluar mereka.if grep -qe "somestring" file
daripada dijalankangrep -qe "somestring" file; if [ $? = 0 ]; then ...
, sehingga klaim yangif [ ...
merupakan bagian dari definisiif
sintaksis tidak hanya menyesatkan tetapi mengarah pada praktik buruk.Berikut ini menjalankan perintah eksternal
command
dan mengembalikan hasilnya.Tanpa tanda kurung / tanda kurung, ini akan mencari variabel alih-alih menjalankan perintah:
Adapun perbedaan antara
$variable
dan"$variable"
, ini menjadi relevan ketika$variable
berisi spasi. Saat menggunakan"$variable"
, seluruh konten variabel akan dimasukkan ke dalam string tunggal bahkan jika konten menyertakan spasi. Saat menggunakan$variable
konten variabel dapat diperluas ke daftar argumen beberapa argumen.sumber
Untuk menjadi pelawan - bash merekomendasikan Anda menggunakan
[[ ... ]]
over the[ ... ]
construct untuk menghindari keharusan mengutip variabel dalam tes dan masalah terkait pemisahan kata yang ditunjukkan oleh yang lain.[
disediakan di bash untuk kompatibilitas POSIX dengan skrip yang dimaksudkan untuk berjalan di bawah#!/bin/sh
atau yang sedang di-port ke bash - untuk sebagian besar, Anda harus menghindarinya[[
.misalnya
sumber
bash
tidak membuat rekomendasi seperti itu; ini menyediakan[[ ... ]]
mana yang bisa lebih nyaman dan memiliki beberapa fungsi yang[ ... ]
tidak, tetapi tidak ada masalah dengan menggunakan dengan[ ... ]
benar .[[
tidak semuanya[
berjalan dan masih banyak kali membuat[
orang tersandung dan kemudian mencoba dan retrofit fitur[[
kembali ke[
hanya untuk gagal dan meninggalkan bug berserakan - itu adil untuk mengatakan itu adalah rekomendasi komunitas sejauh panduan gaya bash paling relevan akan menyarankan tidak pernah digunakan[
.