Kabuk betiği “if” deyimlerinde alıntı değişkenleri arasındaki fark?


9

Bu iki Bash if-ifadesi arasındaki fark nedir? Örneğin

if [ "$FOO" = "true" ]; then

vs

if [ $FOO = "true" ]; then

Fark ne? Her iki ifadenin de aynı şekilde işlediği görülüyor.


Bash'te çift köşeli parantez kullanın ve tırnak işaretlerine ihtiyacınız yoktur ve ek avantajlar elde edersiniz .
sonraki duyuruya kadar duraklatıldı.

@DennisWilliamson Pek değil, eşitlik ve örüntü eşleştirme operatörlerinin sağ tarafında tırnaklara ihtiyacınız var.
Gilles 'SO- kötü olmayı kes'


@Gilles: Bazen hayır. Literal dizeleri veya içermeyen değişkenler için veya boşluk içeren dizeler için kelimenin tam anlamıyla alınması istediğiniz glob karakterleri , sağ taraf tırnak içinde olmalıdır: a='foo bar'; [[ $a == "foo bar" ]]. Ancak, glob karakterleri içermeyen bir değişken olması gerekmez: [[ $a == $a ]]. Sözcük genişletme çift köşeli parantez içinde gerçekleştirilmez. Ve regex eşleştirme için, sağ taraftaki desen alıntı olmamalıdır yoksa dize olarak alınacaktır: [[ $a =~ .*oo.*r ]](desen Ancak bunun yerine ..., un-alıntılanan değişken olmalıdır
. Durduruldu sonraki duyuruya kadar

tam anlamıyla buraya dahil edilme). Glob tarzı desen eşleştirme için, glob karakter değişmezi olsun veya bir değişkende, alıntılanan edilmemelidir: [[ $a == foo* ]]. Gerçek dize örneğimin yanı sıra alıntı yapma gereksinimi için ek örnekler verebilir misiniz?
sonraki duyuruya kadar duraklatıldı.

Yanıtlar:


6

Değeri, $FOOjoker karakter içermeyen tek bir sözcükse \[*?, ikisi aynıdır.

Eğer $FOOatanmamış veya boş ya da birden fazla kelime (yani, boşluk veya içeren $IFS, daha sonra işlem görmeyen versiyonu yazım hatasıdır). Eğer sadece doğru kelime dizisi ise (örneğin 0 -eq 0 -o false), sonuç keyfi olabilir. Bu nedenle, kabuk komut dosyalarında değişkenleri her zaman alıntılamak iyi bir uygulamadır.

Bu arada, "true"alıntı yapılmasına gerek yoktur.


3

Hangi sorunlara yol açabileceğini göstermek için birkaç örnek.

Diyelim ki aşağıdaki iki değişkenimiz var:

FOO="some value"
BAR="some value"

Şimdi tam olarak aynı dizeyi / değeri tutan iki değişkenimiz var. Sonucu test etmek için bazı if ifadeleri yapsaydık, sizin durumunuzda:

if [ $FOO = "$BAR" ]; then echo "match"; else echo "no match"; fi

Bu noktada alacaksınız bash: [: too many arguments. Alıntılanmamış $ FOO artık üç değere sahiptir '[ , some , value'. [test anahtar sözcüğü ne çalıştırılacağını bilmiyor çünkü birinci veya ikinci argümanın operatör olmasını bekliyor.

"$ FOO" teklifini verdiğimizde if, hiçbir kelime bölünmesinin gerçekleşmediği doğru değerlere bakmayı açıkça söylüyoruz .

Başka bir örnek:

my_file="A random file.txt"
  • bunu yapmak rm $my_file, 'A' 'random' 'file.txt' dosyasını kaldırmak anlamına gelir, bu da onu üç dosya yapar.
  • yapıyor rm "$my_file"bir dosya yapar "Rastgele bir dosya.txt" kaldıracaktır.

Umarım sizi bu örneklerle karıştırmam.


0

Burada, ififadelerde veya herhangi bir komutun argümanlarında ve belirli bir durumda komutta alıntı yapmak ya da değil [.

[(İçinde 's yerleşik en Bourne gibi kabuklarına rağmen) ve diğer komuta gibi kullanılabilen komut diğerleri gibi bir komut if, then, elif, elseparçaları if...fitabloların yanı sıra dış if...fitablolar.

Bourne benzeri mermilerde zsh, parametre genişlemesini tırnaksız bırakmak split + glob operatörüdür.

$FOO, $IFSkarmaşık kurallar kullanan karakterler ve dosya adı oluşturma işlemine tabi olan sonuçlarda, [tam olarak bir tane beklediği komuta değişken sayıda argüman oluşturacak şekilde bölünecektir .

Herhangi bir komutun herhangi bir argümanında olduğu gibi, bu $FOOda alıntılanması gerekir, böylece içeriği bir argüman olarak iletilir.

[değişkenlerin alıntılanmasının unutulmamasının kritik olduğu bu komutlardan biridir, çünkü bunu yapmamak birçok uygulamada keyfi bir komut enjeksiyonuna karşılık gelir (değişkenin içeriği bir saldırganın kontrolü altında olabilir).

Bu içerir [arasında yerleşik programı bash, ksh88, ksh93, pdkshve bunların türevleri ve zshve /bin/[bir sargı yaklaşık komut dosyası olarak uygulanacağı Solaris gibi bu sistemlerin ksh'in yerleşiği [.

Bunlar [bazı koşulda aritmetik ifadeleri yorumlayabilir veya kod yürütme sona erebilir değişken isimlerine çalışabilir bu kabuklarda tüm bu yerleşik komutların gibi uygulamalar.

Burada, bir örnek olarak, bashkabukta (aynı zamanda shbirkaç sistemin uygulanması olan GNU projesinin kabuğu ) ve varsayılan değeri $IFS:

bash-5.0$ FOO='-v x[$(reboot)] -o true'
bash-5.0$ if [ $FOO = "true" ]; then echo yes; fi
System rebooting now!
yes

O alıntı ve çünkü değildi çünkü $IFSvarsayılan olarak SPC karakter içeriyor, $FOOiçine bölünmüş oldu -v, x[$(reboot)], -ove true. Bunlardan sadece ikincisi glob operatörleri ( [...]) içerir . Benim durumumda, herhangi bir dosyayla eşleşmedi, bu yüzden olduğu gibi bırakıldı (Bourne benzeri kabukların başka bir özelliği, diğer kabukların çoğu globun eşleşmediğinden şikayetçi olurdu).

Yani isteyen sona erdi o [olsun $xdizi endeks için kuruldu $(reboot)ve çalışan sona erdi reboot(veya -o) olsun trueeşit olduğunu true, dolayısıyla yesçıkışı.

Daha fazla okuma:


-1

Bu özel durumda hiçbir fark yoktur.

Ancak, $FOOboşluk veya bazı özel karakterler içeriyorsa, bir sorunla karşılaşırsınız.

Bu "$FOO"durumda, eşleşmeyi sizi uzay probleminden yalıtan yapmak için toplamda değişkeni kullanacaktır.

Ancak, kullanırsanız $FOOve özel bir durum varsa, if ifadesini etkiler.

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.