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.
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.
Jawaban:
Kutipan diperlukan dalam export foo="$var"
atau local foo="$var"
(atau readonly
, 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 dalam ksh
atau sh
emulasi (atau di export var="$(cmd)"
mana zsh
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 dalam sh
atau ksh
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 dalam sh
/ ksh
emulasi dan bahkan untuk substitusi perintah.
Ada kasus-kasus khusus di mana mengutip diperlukan bahkan dalam cangkang tersebut seperti:
a="b=some value"
export "$a"
Atau lebih umum, jika sesuatu yang tersisa dari =
(termasuk =
) dikutip atau hasil dari ekspansi (seperti export 'foo'="$var"
, export foo\="$var"
atau export foo$((n+=1))="$var"
(yang $((...))
juga harus dikutip sebenarnya) ...). Atau dengan kata lain ketika argumen untuk export
tidak akan menjadi tugas variabel yang valid jika ditulis tanpa export
.
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 & T ksh
dan mksh
.
Jika export
/ local
atau sebagian dari itu adalah hasil dari ekspansi (seperti dalam cmd=export; "$cmd" a="$b"
atau bahkan export$(:) a="$b"
) atau dalam hal-hal seperti dryrun=; $dryrun export a="$b"
), maka tanda kutip diperlukan di setiap shell.
Dalam hal > /dev/null export a="$b"
, kuotasi diperlukan dalam pdksh
dan beberapa turunannya.
Karena command export a="$b"
, tanda kutip diperlukan di setiap shell tetapi mksh
dan ksh93
(dengan peringatan yang sama tentang command
dan export
tidak menjadi hasil dari ekspansi).
Mereka tidak diperlukan dalam shell apa pun ketika ditulis:
foo=$var export foo
(Sintaks itu juga kompatibel dengan shell Bourne tetapi dalam versi terbaru zsh
, hanya berfungsi ketika di sh
/ 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 keluar cmd
masuk export var="$(cmd)"
hilang. Melakukannya karena export var; var=$(cmd)
tidak memiliki masalah itu.
Waspadalah terhadap kasus khusus ini dengan bash
:
$ bash -c 'IFS=; export a="$*"; echo "$a"' bash a b
ab
$ bash -c 'IFS=; export a=$*; echo "$a"' bash a b
a b
Saran saya adalah selalu mengutip.
zsh
tanda kutip yang dibutuhkan untuk local foo="$(cmd)"
karena wordsplitting (tapi tidak nama file generasi) yang dilakukan untuk substitusi perintah kuotasi (tetapi tidak untuk ekspansi parameter kuotasi), kecuali KSH_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:
#!/bin/bash
bar="hi bye"
function foo {
local myvar=${bar}
printf "%s\n" $myvar
printf "%s\n" "$myvar"
}
foo
Penggunaan variabel dalam suatu tugas tampaknya tidak membutuhkan tanda kutip, tetapi ketika Anda menggunakannya, printf
Anda akan membutuhkannya yang dikutip di sana:
printf "%s\n" "$myvar"
CATATAN: Ingat bahwa variabel $IFS
adalah apa yang mengatur apa karakter pemisah.
IFS The Internal Field Separator that is used for word splitting after
expansion and to split lines into words with the read builtin command.
The default value is ``<space><tab><newline>''.
Dengan debugging diaktifkan di Bash kita dapat melihat apa yang terjadi di balik layar.
$ bash -x cmd.bash
+ bar='hi bye'
+ foo
+ local 'myvar=hi bye'
+ printf '%s\n' hi bye
hi
bye
+ printf '%s\n' 'hi bye'
hi bye
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.
bash
dan ksh
di local
/ typeset
... builtin khusus).