Bu, testin nasıl [tanımlandığına dair bir hata olarak düşünülebilecek çok karanlık bir durumdur ; ancak, [birçok sistemde mevcut olan gerçek ikili davranışına uymuyor . Bildiğim kadarıyla söyleyebilirim, sadece belli durumlarda ve bir eşleşen bir değeri olan bir değişken etkiler [gibi operatörü (, !, =,-e , vb.
Nedenini ve Bash ve POSIX mermilerinde nasıl çalışacağını açıklamama izin verin.
Açıklama:
Aşağıdakileri göz önünde bulundur:
x="("
[ "$x" = "(" ] && echo yes || echo no
Sorun değil; Yukarıdakiler hata vermez ve çıktı verir yes. İşlerin böyle olmasını bekliyoruz. İsterseniz karşılaştırma dizesini '1've değerini değiştirebilirsiniz.x ; beklendiği gibi çalışacaktır.
Gerçek /usr/bin/[ikili aynı şekilde davranır unutmayın . Eğer kaçarsan'/usr/bin/[' '(' = '(' ']' hata yoktur, çünkü program argümanların tek bir dize karşılaştırma işleminden oluştuğunu tespit edebilir.
Böcek biz ve ikinci bir ifadeyle olduğunda ortaya çıkar . Geçerli olduğu sürece ikinci ifadenin ne olduğu önemli değildir. Örneğin,
[ '1' = '1' ] && echo yes || echo no
çıktılar yesve açıkça geçerli bir ifadedir; ama ikisini birleştirirsek,
[ "$x" = "(" -a '1' = '1' ] && echo yes || echo no
Ancak ve ancak Bash ifadesini reddeder xolduğu (veya! .
Yukarıdakileri asıl [programı kullanarak çalıştırırsak , yani
'/usr/bin/[' "$x" = "(" -a '1' = '1' ] && echo yes || echo no
hata anlaşılabilir olacaktır: kabuk değişken ikameleri yaptığı için, /usr/bin/[ikili sadece parametreleri alır ( = ( -a 1 = 1ve sonlandırır ], açık parantezlerin bir alt ifade başlatıp başlatmayacağını, orada ve işlem . Elbette, onu iki dize karşılaştırması olarak ayrıştırmak mümkündür, ancak bunu ciddiyetle yapmak, parantezli alt ifadelerle uygun ifadelere uygulandığında sorunlara neden olabilir.
Asıl sorun, [yerleşik kabuğun x, ifadeyi incelemeden önceki değerini artırıyormuş gibi davranmasıdır .
(Bu belirsizlikler ve değişken genişlemeyle ilgili diğerleri, Bash'in uygulamasının ve şimdi [[ ... ]]bunun yerine test ifadelerinin kullanılmasını tavsiye etmesinin büyük bir nedenidir .)
Çözüm geçicidir ve genellikle eski shkabukları kullanan komut dosyalarında görülür . xİfadenin bir dize karşılaştırması olarak tanınmasını sağlamak için genellikle dizelerin önüne (her iki değer karşılaştırılır) bir "güvenli" karakter eklersiniz :
[ "x$x" = "x(" -a "x$y" = "x1" ]
[[ "$x" = '1' && "$y" = '1' ]]