Saya memiliki skrip shell bernama 'teleport.sh' seperti ini:
if [ $1="1" ];
then
shift
mv "$@" ~/lab/Sun
elif [ $1="2" ];
then
shift
mv "$@" ~/lab/Moon
elif [ $1="3" ];
then
shift
mv "$@" ~/lab/Earth
fi
Ketika saya mengeksekusi:
sh teleport.sh 2 testfile
Ini testfile
dipindahkan ke ~/lab/Sun
direktori, yang membingungkan saya karena saya tidak meneruskan 1 atau '1' ke skrip itu.
Ada apa di sini?
$var
,$(cmd)
, dan bahkan`cmd`
[yang$(cmd)
harus disukai]). Ada beberapa kasus tepi di mana Anda tidak perlu mengutip, tetapi selalu melakukannya tidak akan merugikan.$(cmd)
adalah substitusi perintah , (kebanyakan) sama dengan`cmd`
. Lihat mywiki.wooledge.org/CommandSubstitution dan mywiki.wooledge.org/BashFAQ/082Jawaban:
Menggunakan spasi memperbaiki masalah Anda.
Padahal ini lebih rapi:
sumber
$1="1"
sintaks asli "berfungsi" sama sekali (menghasilkan hasil yang benar). Bagaimana sebenarnya[
/test
builtin menafsirkan ungkapan itu?test
hanya melihat satu argumen ("nilai-l"). Tanpa argumen lain ("operator" dan "nilai-r"), tidak ada yang perlu diuji, jaditest
katakan saja "ok, well yeah, Anda memberi saya sesuatu dan itu harus benar-benar benar".$1="1"
adalah$1
concatenated oleh=1
Hal pertama yang jelas adalah Anda harus memberi jarak di antara argumen
[
,test
atau[[
:Ketika berada di Bash,
[[ ]]
disarankan menggunakan karena tidak melakukan hal-hal yang tidak perlu untuk ekspresi kondisional seperti pemisahan kata dan perluasan nama path. Mengutip kutipan ganda juga tidak diperlukan. Operator yang lebih mudah dibaca==
juga dapat digunakan.Ditambahkan catatan: Jika operan kedua juga mengandung variabel, mengutip diperlukan karena dapat dikenakan pencocokan pola jika mengandung karakter dikenali seperti
*
,?
,[]
, dll .. Jika diperpanjang globbing atau pencocokan pola diaktifkan denganshopt -s extglob
, bentuk-bentuk lain seperti@()
,!()
, dll juga akan dikenali sebagai pola. Lihat Pencocokan Pola .Dengan operator seperti
<
dan>
mungkin masih perlu karena saya pernah menemukan bug di mana tidak mengutip argumen kedua menyebabkan hasil yang berbeda.Sedangkan untuk operan pertama, tidak ada yang berlaku.
Pertimbangkan variasi yang lebih sederhana ini juga:
Atau kental:
"${@:2}"
adalah bentuk ekspansi substring atau ekspansi anggota array di mana2
offset. Ini membuat ekspansi dimulai dari nilai kedua. Dengan ini kita mungkin tidak perlu menggunakanshift
.Yang ditambahkan
--
mencegah mencegahmv
nama file dimulai dengan tanda hubung (-
) sebagai opsi yang tidak valid.sumber
;&
alih-alih;;
(ksh, bash, zsh saja). Tapi kemudianbreak
masih tidak mencegah kejatuhan,break
hanya untuk keluar dari lingkaran.if
tetapi untuk[
perintah.[[ $foo == $bar ]]
akan melakukan pencocokan pola, tetapi[[ $foo == "$bar" ]]
tidak akan.Untuk menjawab pertanyaan mengapa ini terjadi, perilaku
[
aliastest
ini didokumentasikan dalam POSIX :Anda memberikan 1 argumen
2=1
, yang bukan nol, dan karenanyatest
keluar dengan sukses.Seperti yang ditunjukkan oleh posting lain (dan shellcheck ), jika Anda ingin membandingkan untuk kesetaraan, Anda harus melewati 3 argumen
2
,=
dan1
.sumber
Saya hanya ingin merekomendasikan alternatif yang portabel namun juga lebih rapi. Bash tidak universal (dan jika Anda tidak perlu universal, mengapa Anda menulis skrip shell?)
(Catatan untuk pedants: ya, saya tahu tanda kutip
$action
padacase "$action" in
baris yang tidak perlu, tapi saya merasa yang terbaik adalah untuk menempatkan mereka di sana pula, sehingga pembaca masa depan tidak harus ingat itu.)sumber
/bin/sh
skrip portabel , jika Anda membutuhkannya; jika tidak, tulis dalam bahasa skrip yang tidak kalah mengerikan dari shell. Interpreter Perl dasar pada kenyataannya lebih mungkin untuk hadir dalam lingkungan eksklusif warisan dan lingkungan tertanam cut-down daripada Bash.