Yerel bir ödevin sağındaki tırnakları güvenle atlayabilir miyim?
function foo {
local myvar=${bar}
stuff()
}
Ben esas olarak ilgileniyorum bash
, fakat diğer mermilerdeki köşe davaları ile ilgili herhangi bir bilgi açığız.
Yerel bir ödevin sağındaki tırnakları güvenle atlayabilir miyim?
function foo {
local myvar=${bar}
stuff()
}
Ben esas olarak ilgileniyorum bash
, fakat diğer mermilerdeki köşe davaları ile ilgili herhangi bir bilgi açığız.
Yanıtlar:
Tırnaklar ihtiyaç vardır export foo="$var"
ya da local foo="$var"
(ya da readonly
, typeset
, declare
ve diğer değişken ilan komutlar olarak):
dash
sh
NetBSD (ayrıca Almquist kabuk göre).sh
FreeBSD 9.2 veya daha büyük (bkz 9.3 değişikliği )yash
zsh
5.1'den önceki sürümlerde ksh
veya sh
öykünme sırasında (veya başka export var="$(cmd)"
yerde zsh
sözcük ayırmayı nerede gerçekleştireceği içindir (globbing değil)).Aksi taktirde değişken genişlemesi, herhangi başka bir komutta olduğu gibi herhangi bir argümandaki gibi sözcük bölmeye ve / veya dosya ismi oluşturulmasına tabi olacaktır.
Ve gerekli değildir:
bash
ksh
(tüm uygulamalar)sh
FreeBSD 9.3 veya daha yenish
(2005'ten beri)zsh
İçinde zsh
, split + glob, parametrenin genişlemesi üzerine, içinde sh
veya öykünmedikçe asla yapılmaz ksh
, ancak split (glob değil) komut değiştirme üzerine yapılır. 5.1 sürümünden beri export
/ local
ve diğer bildirim komutları, yukarıdaki diğer kabuklarda olduğu gibi çift anahtar kelime / yerleşik komutlar haline gelmiştir ; bu, alıntı sh
/ ksh
emülasyonda ve hatta komut değiştirme için bile alıntı yapılması gerekmediği anlamına gelir .
Aşağıdaki gibi kabuklarda bile alıntı yapılması gereken özel durumlar vardır:
a="b=some value"
export "$a"
Ya da daha genel olarak, eğer =
(dahil olanlar dahil =
) kalanlar kote edilmişse ya da bir genişlemenin sonucu (mesela export 'foo'="$var"
, export foo\="$var"
ya da export foo$((n+=1))="$var"
( $((...))
gerçekte kote edilmelidir) ...). Ya da başka bir deyişle, eğer argüman export
geçerli bir değişken ataması olmazsa yazılmamış olsaydı export
.
Eğer export
/ local
komut adı kendisi alıntılanmıştır (hatta gibi kısmen "export" a="$b"
, 'ex'port a="$b"
, \export a="$b"
hatta ""export a="$b"
), etrafında tırnak $b
AT & T dışındaki ihtiyaç vardır ksh
ve mksh
.
Eğer export
/ local
veya bir kısmı bir miktar genişlemenin (içinde cmd=export; "$cmd" a="$b"
veya hatta export$(:) a="$b"
) veya benzeri şeylerin sonucu dryrun=; $dryrun export a="$b"
ise, her kabukta tırnaklar gerekir.
Bu durumda > /dev/null export a="$b"
, tırnaklara pdksh
ve türevlerinden bazılarına ihtiyaç duyulur .
İçin command export a="$b"
, tırnak her kabuk ancak ihtiyaç vardır mksh
ve ksh93
(yaklaşık aynı uyarılar ile command
ve export
bazı genişleme sonucu olarak).
Yazıldığında hiçbir kabuğa ihtiyaç duymazlar:
foo=$var export foo
(bu sözdizimi Bourne kabuğuyla da uyumludur ancak son sürümlerinde zsh
, yalnızca sh
/ ksh
öykünme sırasında çalışır).
( var=value local var
davranış kabukları arasında değişir gibi kullanılmaması gerektiğini unutmayın ).
Ayrıca kullanarak unutmayın export
bir atama ile de araçlar çıkış durumu olduğu cmd
içinde export var="$(cmd)"
kaybolur. Bunu yapmanın bu export var; var=$(cmd)
sorunu yok.
Ayrıca bu özel olaya dikkat edin bash
:
$ bash -c 'IFS=; export a="$*"; echo "$a"' bash a b
ab
$ bash -c 'IFS=; export a=$*; echo "$a"' bash a b
a b
Tavsiyem her zaman alıntı yapmak olacaktır.
zsh
Tırnak işaretleri için gerekli olduğunu unutmayın; local foo="$(cmd)"
çünkü , tırnak işaretleri altında olmayan (ancak dosya adı oluşturmayan) , tırnak işaretleri altında olmayan komut değiştirme işlemleri için (ancak KSH_TYPESET
tırnak işaretleri olmadan parametre genişletmeleri için) yapılmaz (bu durumda tırnak işaretleri gerekli değildir) . Mantıklı olmak? Yok hayır? Sonra ne yaptığınızı tam olarak bilmediğiniz sürece her zaman her şeyi isteyin.
Genelde, beyaz boşluklar gibi karakterlerin olabileceği değişkenlerin kullanımını alıntılarım. Aksi takdirde, bu gibi sorunlarla karşılaşırsınız:
#!/bin/bash
bar="hi bye"
function foo {
local myvar=${bar}
printf "%s\n" $myvar
printf "%s\n" "$myvar"
}
foo
Değişkenin bir ödevde kullanımı, alıntılara ihtiyaç duymuyor gibi görünmektedir, ancak kullanmaya başladığınızda olduğu gibi, printf
orada alıntı yapmanız gerekir.
printf "%s\n" "$myvar"
NOT: Değişkenin $IFS
, ayırıcı karakterlerin ne olduğunu yöneten şey olduğunu unutmayın .
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>''.
Bash'de hata ayıklama etkinken, sahne arkasında neler olduğunu görebiliriz.
$ 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
Yukarıda, değişkenin $bar
para cezasına çarptırıldığını görebiliyoruz, $myvar
ancak kullanmaya gittiğimizde, kullanmaya başladığımız $myvar
zamanın içeriğinin bir parçası olmalıydık $myvar
.
bash
ve ksh
de local
/ typeset
... özel yerleşikleri).