Bisakah saya dengan aman menghilangkan tanda kutip di sisi kanan tugas lokal?
function foo {
local myvar=${bar}
stuff()
}
Saya terutama tertarik bash
, tetapi setiap info tentang kasus sudut di kulit lain dipersilakan.
shell-script
quoting
assignment
rahmu
sumber
sumber
Jawaban:
Kutipan diperlukan dalam
export foo="$var"
ataulocal foo="$var"
(ataureadonly
,typeset
,declare
dan variabel menyatakan lainnya perintah ) di:dash
sh
dari NetBSD (juga didasarkan pada Almquist shell).sh
FreeBSD 9.2 atau lebih tua (lihat perubahan di 9.3 )yash
zsh
dengan versi sebelum 5.1 dalamksh
ataush
emulasi (atau diexport var="$(cmd)"
manazsh
akan melakukan pemisahan kata sebaliknya (tidak menggumpal)).Seperti sebaliknya, ekspansi variabel akan dikenakan pemisahan kata dan / atau pembuatan nama file seperti dalam argumen apa pun terhadap perintah lain.
Dan tidak diperlukan di:
bash
ksh
(semua implementasi)sh
dari FreeBSD 9.3 atau yang lebih barush
(sejak 2005)zsh
In
zsh
, split + glob tidak pernah dilakukan pada ekspansi parameter, kecuali dalamsh
atauksh
emulasi, tetapi split (bukan glob) dilakukan pada substitusi perintah. Sejak versi 5.1,export
/local
dan perintah deklarasi lainnya telah menjadi kata kunci ganda / perintah builtin seperti pada shell lain di atas, yang berarti mengutip tidak diperlukan, bahkan dalamsh
/ksh
emulasi dan bahkan untuk substitusi perintah.Ada kasus-kasus khusus di mana mengutip diperlukan bahkan dalam cangkang tersebut seperti:
Atau lebih umum, jika sesuatu yang tersisa dari
=
(termasuk=
) dikutip atau hasil dari ekspansi (sepertiexport 'foo'="$var"
,export foo\="$var"
atauexport foo$((n+=1))="$var"
(yang$((...))
juga harus dikutip sebenarnya) ...). Atau dengan kata lain ketika argumen untukexport
tidak akan menjadi tugas variabel yang valid jika ditulis tanpaexport
.Jika
export
/local
nama perintah itu sendiri dikutip (bahkan di bagian seperti"export" a="$b"
,'ex'port a="$b"
,\export a="$b"
, atau bahkan""export a="$b"
), tanda kutip sekitar$b
diperlukan kecuali pada AT & Tksh
danmksh
.Jika
export
/local
atau sebagian dari itu adalah hasil dari ekspansi (seperti dalamcmd=export; "$cmd" a="$b"
atau bahkanexport$(:) a="$b"
) atau dalam hal-hal sepertidryrun=; $dryrun export a="$b"
), maka tanda kutip diperlukan di setiap shell.Dalam hal
> /dev/null export a="$b"
, kuotasi diperlukan dalampdksh
dan beberapa turunannya.Karena
command export a="$b"
, tanda kutip diperlukan di setiap shell tetapimksh
danksh93
(dengan peringatan yang sama tentangcommand
danexport
tidak menjadi hasil dari ekspansi).Mereka tidak diperlukan dalam shell apa pun ketika ditulis:
(Sintaks itu juga kompatibel dengan shell Bourne tetapi dalam versi terbaru
zsh
, hanya berfungsi ketika dish
/ksh
emulasi).(perhatikan bahwa
var=value local var
tidak boleh digunakan karena perilaku bervariasi di seluruh cangkang).Perhatikan juga bahwa menggunakan
export
dengan penugasan juga berarti bahwa status keluarcmd
masukexport var="$(cmd)"
hilang. Melakukannya karenaexport var; var=$(cmd)
tidak memiliki masalah itu.Waspadalah terhadap kasus khusus ini dengan
bash
:Saran saya adalah selalu mengutip.
sumber
zsh
tanda kutip yang dibutuhkan untuklocal foo="$(cmd)"
karena wordsplitting (tapi tidak nama file generasi) yang dilakukan untuk substitusi perintah kuotasi (tetapi tidak untuk ekspansi parameter kuotasi), kecualiKSH_TYPESET
diaktifkan, di mana kutipan kasus tidak diperlukan. Masuk akal? Tidak? Maka selalu kutip semuanya kecuali Anda tahu persis apa yang Anda lakukan.Saya biasanya mengutip setiap penggunaan variabel di mana mungkin ada karakter seperti spasi putih. Kalau tidak, Anda akan mengalami masalah seperti ini:
Penggunaan variabel dalam suatu tugas tampaknya tidak membutuhkan tanda kutip, tetapi ketika Anda menggunakannya,
printf
Anda akan membutuhkannya yang dikutip di sana:CATATAN: Ingat bahwa variabel
$IFS
adalah apa yang mengatur apa karakter pemisah.Contoh
Dengan debugging diaktifkan di Bash kita dapat melihat apa yang terjadi di balik layar.
Dalam contoh di atas kita dapat melihat bahwa variabel,
$bar
dibagikan dengan baik ke$myvar
tetapi kemudian ketika kita pergi untuk menggunakan$myvar
kita harus menyadari isi$myvar
ketika kita pergi untuk menggunakannya.sumber
bash
danksh
dilocal
/typeset
... builtin khusus).