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 yes
ve 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 x
olduğ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
=
1
ve 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 sh
kabukları 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' ]]