$ VAR vs $ {VAR} ve alıntı yapmak veya alıntı yapmak


Yanıtlar:


99

VAR=$VAR1basitleştirilmiş bir sürümüdür VAR=${VAR1}. İkincisinin yapamayacağı şeyler vardır, örneğin bir dizi dizinine referans verebilir (taşınabilir değil) veya bir alt dizgiyi kaldırabilir (POSIX taşınabilir). POSIX özelliklerinde Yeni Başlayanlar İçin Bash Kılavuzu ve Parametre Genişletme bölümündeki Değişkenler hakkında daha fazlası bölümüne bakın .

Bir değişkenin etrafındaki tırnak işaretlerini kullanarak rm -- "$VAR1"ya da rm -- "${VAR}"olduğu gibi iyi bir fikirdir. Bu, değişkenin içeriğini atomik bir birim yapar. Değişken değeri boşluklar ( $IFSözel değişkendeki karakterler, varsayılan olarak boşluklar) veya globbing karakterleri içeriyorsa ve alıntı yapmıyorsanız, her kelime, genişlemesi size ne kadar argüman yaparsa, dosya adı oluşturma (globbing) olarak kabul edilir. yapıyorum.

$ find .
.
./*r*
./-rf
./another
./filename
./spaced filename
./another spaced filename
./another spaced filename/x
$ var='spaced filename'
# usually, 'spaced filename' would come from the output of some command and you weren't expecting it
$ rm $var
rm: cannot remove 'spaced': No such file or directory
# oops! I just ran 'rm spaced filename'
$ var='*r*'
$ rm $var
# expands to: 'rm' '-rf' '*r*' 'another spaced filename'

$ find .
.
./another
./spaced filename
./another spaced filename
$ var='another spaced filename'
$ rm -- "$var"
$ find .
.
./another
./spaced filename

Taşınabilirlikte: POSIX.1-2008 bölüm 2.6.2'ye göre , küme parantezleri isteğe bağlıdır.


@shawn sorumu güncellediğim için taşınabilirliği de merak ediyorum
xenoterracide

@shawn: Örneğinizin geçerli olduğundan şüpheliyim. var1=$varGenişlemenin hata verdiği herhangi bir gerçek kabuk örneğiniz var mı?
alex,

@ alex: Teşekkürler. Bunu komut satırında test ettiğimi sanıyordum, ama yanlış yaptım. Örneği değiştirdim.
Shawn J. Goff,

Güncellenen örnekte, genellikle bir köşe örneği olduğu için, alıntılanan sürümü genellikle istemeniz gerektiğini aklınızda bulundurmanız daha iyi olacaktır.
alex

9
@Shawn: Bir ödevde tırnak gerekli değildir . Bunlar, diğer birçok kullanımda gereklidir export VAR=$VAR1. Parantezlere gelince, isteğe bağlıdırlar (alıntı yaptığınız bölümün dördüncü paragrafını kontrol edin; bu durum tüm POSIX ve POSIX kabuklarında geçerlidir).
Gilles

60

${VAR}ve $VARtam olarak eşdeğerdir. Düz değişken bir genişleme için, kullanmanın tek nedeni ${VAR}, ayrıştırmanın değişken ismine çok fazla karakter girmesidir ${VAR1}_$VAR2(olduğu gibi (parantez olmadan eşdeğer olur ${VAR1_}$VAR2)). Çoğu süslenmiş genişleme ( ${VAR:=default},, ${VAR#prefix}…) diş telleri gerektirir.

Bir değişken atamasında, alan bölme (yani değerdeki boşlukta bölme) ve yol adı genişletme (yani globbing) kapatılır, yani tüm POSIX kabuklarında ve duyduğum tüm POSIX öncesi sh'lerinde VAR=$VAR1tam olarak eşdeğerdir VAR="$VAR1". (POSIX ref: basit komutlar ). Aynı nedenden dolayı, değişmez dizgeye VAR=*güvenilir bir şekilde ayarlanır ; Tabii setleri için çünkü ilk etapta ayrı kelimedir. Genel konuşmak kabuk sözdizimi, örneğin tek bir kelime beklediğini nerede, çift tırnak gereksizdir içinde (ancak desende), ancak orada bile dikkatli olmak gerekir: örneğin POSIX belirtirVAR*VAR=a bVARabcase … inyönlendirme hedefleri ( >$filename), komut dosyalarında alıntı yapılmasını gerektirmez, ancak bash dahil olmak üzere birkaç kabuk, komut dosyalarında bile çift tırnak işareti gerektirir. Bkz . Çift alıntı ne zaman gereklidir? daha kapsamlı bir analiz için.

Diğer durumlarda, özellikle birçok kabukta ( export VAR="${VAR1}"aynı anda yazılabilir export "VAR=${VAR1}") çift ​​tırnaklara ihtiyacınız vardır (POSIX bu davayı açık bırakır). Bu davanın basit ödevlerle benzerliği ve çift tırnak kullanmaya gerek duymadığınız davalar listesinin dağınık doğası, bölmek ve kürek almak istemediğiniz sürece neden sadece çift tırnak kullanmanızı öneririm.


2
Genel bir kural olarak, değerin herhangi bir IFSkarakter içermediğini bildiğim halde , alışkanlıkta olmak istediğim için değişken açılımları her zaman alıntılayacağım . Bunun tek istisnası, değişken ataması yaparken değeri alıntılamıyorum (değer boşluk içerdiği zaman gerekli olmadıkça). Bu, editör sözdizimini, bunun gibi komut ikameleri olduğunda daha kullanışlı hale getirir FOO=$(BAR=$(BAZ=blah; printf %s "${BAZ}"); printf %s "${BAR}"). Her şeyi "string" rengini renklendirmek yerine iç içe geçmiş kodun sözdizimini vurgularım. Bu da geri tepmelerden kaçınmamın nedeni budur.
Richard Hansen,

>$filePOSIX betiklerinde TAMAM iken , etkileşimli olmasa bile bash değil (POSIX uyumluluğu $POSIXLY_CORRECTveya --posix... ile zorlanmadıkça ).
Stéphane Chazelas

Tekliflerin gerekmediği doğru olsa da VAR=$VAR1, bazen local VAR=$VAR1bazı yönlerden, en azından bazı mermilerde farklı şekilde çalıştığımı hatırladığım için şaşırdım . Ama atm, ayrılığı yeniden üretemiyorum.
dubiousjim

Tamam, hatırladığım sorunu buldum . Sadece bazı mermilerde ortaya çıkıyor.
dubiousjim

@dubiousjim local VAR=$VAR1gibidir export VAR=$VAR1, kabuğa bağlıdır.
Gilles

8

alıntı

İkili teklifin değişken genişleme için kullanıldığını ve tekli teklifin güçlü alıntı için, yani genişleme için kullanıldığını düşünün.

Genişleme:

this='foo'
that='bar'
these="$this"
those='$that'

Çıktı:

for item in "$this" "$that" "$these" "$those"; do echo "$item"; done
foo
bar
foo
$that

Bir kaç nedenden dolayı, en iyi uygulama olarak kabul edilenler arasında ve okunabilirlik için mümkün olan her yerde tırnak kullanmanız gerektiğini belirtmek faydalı olabilir. Ayrıca Bash, zaman zaman ve çoğu zaman görünüşte mantıksız veya mantıksız / beklenmedik şekillerde ilginç olduğu için ve tırnak, beklentilerin açıkça ortaya çıkmasına neden olur ve bu da bu hata yüzeyini (veya bunun potansiyelini) azaltır.

Ve alıntı yapmamak tamamen yasal olsa da ve çoğu durumda çalışacak olsa da, bu işlevsellik kolaylık sağlamak için sağlanmıştır ve muhtemelen daha az taşınabilirdir. niyet ve beklentiyi yansıtmayı garanti eden tamamen resmi bir uygulama alıntı yapmaktır.

ikame

Şimdi yapının "${somevar}"ikame işlemleri için kullanıldığını da göz önünde bulundurun . Değiştirme ve diziler gibi birkaç kullanım durumu.

Değiştirme (sıyırma):

thisfile='foobar.txt.bak'
foo="${thisfile%.*}"   # removes shortest part of value in $thisfile matching after '%' from righthand side
bar="${thisfile%%.*}"  # removes longest matching

for item in "$foo" "$bar"; do echo "$item"; done
foobar.txt
foobar

Değiştirme (değiştirme):

foobar='Simplest, least effective, least powerful'
# ${var/find/replace_with}
foo="${foobar/least/most}"   #single occurrence
bar="${foobar//least/most}"  #global occurrence (all)

for item in "$foobar" "$foo" "$bar"; do echo "$item"; done
Simplest, least effective, least powerful
Simplest, most effective, least powerful
Simplest, most effective, most powerful

Diziler:

mkdir temp
# create files foo.txt, bar.txt, foobar.txt in temp folder
touch temp/{foo,bar,foobar}.txt
# alpha is array of output from ls  
alpha=($(ls temp/*))

echo "$alpha"         #  temp/foo.txt
echo "${alpha}"       #  temp/foo.txt
echo "${alpha[@]}"    #  temp/bar.txt  temp/foobar.txt  temp/foo.txt
echo "${#alpha}"      #  12 # length of first element (implicit index [0])
echo "${#alpha[@]}"   #  3  # number of elements
echo "${alpha[1]}"    #  temp/foobar.txt # second element
echo "${#alpha[1])"   #  15 # length of second element

for item in "${alpha[@]}"; do echo "$item"; done
temp/bar.txt
temp/foobar.txt
temp/foo.txt

Bunların hepsi, "${var}"ikame yapısının yüzeyini zar zor çiziyor . Bash kabuk komut dosyası için kesin referans libre çevrimiçi referansıdır, TLDP Linux Belgelendirme Projesihttps://www.tldp.org/LDP/abs/html/parameter-substitution.html


1
çok bilgilendirici.
orion elenzil

0
ls -la

lrwxrwxrwx.  1 root root      31 Nov 17 13:13 prodhostname
lrwxrwxrwx.  1 root root      33 Nov 17 13:13 testhostname
lrwxrwxrwx.  1 root root      32 Nov 17 13:13 justname

sonra o zaman:

env=$1
    if [ ! -f /dirname/${env}hostname ]

kıvrım kullanmanın daha net bir örneği olarak görülmeye değer

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.