Neden [-n] [-n “”] gibi yanlış değil?


20

Benim sorum bu kod tarafından üretilen getiri değerleridir:

if [ -n ]; then echo "true"; else echo "false"; fi

Bu yazdırır true.

Tamamlayıcı testi de kullanılarak [ -z ]basılır true:

if [ -z ]; then echo "true"; else  echo "false"; fi

Yukarıdaki kodda, [ -n ]sınama neden hiç geçilmeyen, null değil, dize değerini varsayıyor?

Aşağıdaki kod yazdırılıyor false. Bu, geçirilen dize değerinin null olması ve sıfır uzunluğundan dolayı beklenir.

if [ -n "" ]; then echo "true"; else  echo "false"; fi

Yanıtlar:


14

[x] eşdeğerdir [ -nx] bile x ile başlar -sağlanan hiçbir işlenen yoktur.

$ [ -o ] ; echo $?
0
$ [ -eq ] ; echo $?
0
$ [ -n -o ] ; echo $?
0
$ [ -n -eq ] ; echo $?
0

4
Tarihsel olarak, [ -t ]stdout'un bir terminal olup olmadığını (kısa için [ -t 1 ]) ve bazı kabukları hala yapıyorsa ( ksh93sadece -thazır olduğunda ) kullandığına dikkat edin, bu nedenle kullanmak [ -n "$var" ]daha iyidir [ "$var" ]. Yine de bazı eski başarısız olur rağmen testdeğerleri için uygulamaları $vargibi =bu durumda, [ "" != "$var" ]ya [ "x$var" != x ]veya case $x in "")...daha iyi olabilir.
Stéphane Chazelas,

3
-oBurada ilginç bir seçim . Gibi bazı kabukları içinde bash, -obir birli (bir seçenek kümesi ise testi) ve ikili (veya) operatörü hem şeyler seversin, olduğu [ ! -o monitor ]belirsizdir. monitorSeçeneğin ayarlanmadığını mı !yoksa monitorboş olmayan dize mi olduğunu test ediyor mu? POSIX kuralları karar verir: ikincisi (bununla farklı [[ ! -o monitor ]]).
Stéphane Chazelas,

30

[ -n ]-ntesti kullanmaz .

-nİçinde [ -n ]hiç bir test değildir. Orada arasında yalnızca bir argüman olduğunda [ve ]argüman boş olup olmadığını görmek için test edilir bir dizesi olduğunu. Bu dizgenin öncüsü olsa bile -, yine de bir test değil, bir işlenen olarak yorumlanır. Dize yana -nboş değil - iki karakter içeriyor, -ve n, değil sıfır karakterler-- [ -n ]değerlendirir true.

As Ignacio Vazquez-Abrams diyor , nerede stringtek bağımsız değişken test üzerinde gerçekleştirilen olduğu stringiçinde deney tarafından kendisine gerçekleştirilen aynıdır . Ne zaman olur , hiçbir şey özel olmuyor. İçinde ve ikinci yılında sadece dizeleri Boş olup olmadığı test edilen.[ string ][ -n string ]string-n-n[ -n ]-n[ -n -n ]

Orada arasında yalnızca bir argüman olduğunda [ve ]argüman nonemptiness için test edilecek bir dize, bir test olarak aynı adlandırılacak bir sorun olsa bile, her zaman olduğu. Benzer şekilde, orada ikisi arasında argümanlar olduğunda [ve ]ve bunların ilkidir -n, ikincisi ise bir test olarak aynı adlandırılacak bir sorun olsa bile, her zaman nonemptiness için test edilecek bir dizedir. Bunun nedeni basitçe sözdiziminin , dize işleneni [arasındaki [ve ]sonrasındaki tek bir argüman olduğu konusunda ısrarcı olmasıdır -n.

Testi [ -n ]kullanmayan aynı sebepten dolayı -ntesti [ -z ]kullanmaz -z.


Sen hakkında daha fazla bilgi edinebilirsiniz [içinde bashbunun için yardım inceleyerek. Yerleşik bir kabuk olduğuna dikkat edin :

$ type [
[ is a shell builtin

Böylece help [yardım almak için koşabilirsiniz :

$ help [
[: [ arg... ]
    Evaluate conditional expression.

    This is a synonym for the "test" builtin, but the last argument must
    be a literal `]', to match the opening `['.

Hangi testlerin desteklendiğini ve nasıl çalıştıklarını içeren daha fazla bilgi için yardımı görmeniz gerekir test. Komutu çalıştırdığınızda help testayrıntılı bir liste alırsınız. Hepsini çoğaltmak yerine, dize operatörleri ile ilgili bölüm:

      -z STRING      True if string is empty.

      -n STRING
         STRING      True if string is not empty.

      STRING1 = STRING2
                     True if the strings are equal.
      STRING1 != STRING2
                     True if the strings are not equal.
      STRING1 < STRING2
                     True if STRING1 sorts before STRING2 lexicographically.
      STRING1 > STRING2
                     True if STRING1 sorts after STRING2 lexicographically.

Buna dikkat edin -n STRINGve STRINGaynı şeyi yapın: dizenin STRINGboş olmadığını test ederler .


2
İyi açıklama
Sergiy Kolodyazhnyy

1
Belki de bunun alıntılanmamış değişkenler için ima ettiğinden bahsedin, bunun gibi: paste.ubuntu.com/25831047
Sergiy Kolodyazhnyy

1
@SergiyKolodyazhnyy Ayrı bir cevapta daha iyi olabileceğini düşünüyorum. Ayarlanmamış, ayarlanmış ancak boş ancak yalnızca IFSboşluk içeren değişkenler bunu yapar; sıfır yerine birden çok sözcük içeren değişkenler başka bir etki oluşturur ve tamamen farklı bir testin çalışmasına neden olabilir. Kelimenin tam anlamıyla işlenen olma niyetiyle görünen dizeler yalnızca boşluk veya sekme içermiyorsa veya alıntı yaparlarsa düzgün çalışacaktır. Bu konuyu erişilebilir bir şekilde ele alsaydım cevap daha uzun ve daha karmaşık hale gelirdi. Cevap göndermeye karar verirseniz, bu konuda @ burada bana çekinmeyin!
Eliah Kagan

@Eliah Kagan, cevabınız daha eksiksiz ve ayrıntılı olmasına rağmen, Ignacio Vazquez-Abrams'ın cevabı sorumu cevapladı.
Ravi Kumar

1
Bence sebebi eksik ve bu şekilde olmak zorundasın: Bu olmasa bile, [ "$var" ]bir test olarak kullanılamaz, çünkü $vargenişleyebilir -n.
R.

12

[ -n ]doğrudur çünkü [komut (aka testkomut) verilen argüman sayısına göre hareket eder . Yalnızca tek bir argüman verilirse, argüman boş olmayan bir dize ise sonuç "true" olur. "-n", boş değil, dolayısıyla "true" olmak üzere 2 karakterli bir dizedir.

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.