Mengapa [-n] tidak salah seperti [-n ""]?


20

Pertanyaan saya adalah nilai pengembalian yang dihasilkan oleh kode ini:

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

Ini mencetak true.

Tes pelengkap menggunakan [ -z ]cetak juga true:

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

Dalam kode di atas, mengapa [ -n ]tes menganggap nilai string yang tidak lulus sama sekali, bukan nol?

Kode di bawah ini dicetak false. Ini diharapkan karena nilai string yang diteruskan adalah nol dan panjang nol.

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

Jawaban:


14

[x] sama dengan [ -nx] bahkan jika x dimulai dengan -asalkan tidak ada operan.

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

4
Perhatikan bahwa secara historis, [ -t ]sedang menguji apakah stdout adalah terminal (kependekan [ -t 1 ]) dan beberapa shell masih melakukannya (dalam kasus ksh93hanya ketika itu -tliteral), jadi lebih baik digunakan [ -n "$var" ]daripada [ "$var" ]. Meskipun itu masih akan gagal dalam beberapa testimplementasi lama untuk nilai-nilai $varsuka =, dalam hal ini [ "" != "$var" ]atau [ "x$var" != x ]atau case $x in "")...mungkin lebih baik.
Stéphane Chazelas

3
Pilihan menarik di -osini. Dalam beberapa shell seperti bash, -okeduanya merupakan operator unary (tes jika opsi diatur) dan biner (atau), sehingga hal-hal seperti [ ! -o monitor ]bersifat ambigu. Apakah menguji bahwa monitorpilihan tidak diatur, atau yang baik !atau monitorstring non-kosong? Aturan POSIX memutuskan: yang terakhir (berbeda dengan [[ ! -o monitor ]]).
Stéphane Chazelas

30

[ -n ]tidak menggunakan -ntes.

The -ndalam [ -n ]bukan tes sama sekali. Ketika hanya ada satu argumen di antara [dan ], argumen itu adalah string yang diuji untuk melihat apakah argumen itu kosong. Bahkan ketika string itu memiliki pimpinan -, itu masih ditafsirkan sebagai operan, bukan tes. Karena string -ntidak kosong - itu berisi dua karakter, -dan n, bukan nol karakter - [ -n ]dievaluasi menjadi true.

Seperti yang dikatakan Ignacio Vazquez-Abrams , di mana stringada satu argumen, tes yang dilakukan stringdalam sama dengan tes yang dilakukan oleh . Ketika kebetulan , tidak ada yang istimewa terjadi. The dalam dan yang kedua di hanya string sedang diuji untuk kekosongan.[ string ][ -n string ]string-n-n[ -n ]-n[ -n -n ]

Ketika hanya ada satu argumen di antara [dan ], argumen itu selalu merupakan string yang akan diuji untuk kekosongan, bahkan jika itu dinamai sama dengan tes. Demikian pula, ketika ada dua argumen di antara [dan ]dan yang pertama adalah -n, yang kedua selalu merupakan string yang akan diuji untuk nonemptiness, bahkan jika kebetulan diberi nama sama dengan tes. Ini hanya karena sintaks untuk [menegaskan bahwa argumen tunggal antara [dan ]atau sesudahnya -nadalah operan string.

Untuk alasan yang sama yang [ -n ]tidak menggunakan -ntes, [ -z ]tidak menggunakan -ztes.


Anda dapat mempelajari lebih lanjut tentang [di bashdengan memeriksa bantuan untuk itu. Perhatikan bahwa shell adalah builtin :

$ type [
[ is a shell builtin

Dengan demikian Anda dapat lari help [untuk mendapatkan bantuan tentang hal itu:

$ 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 `['.

Untuk informasi lebih lanjut, termasuk tes apa yang didukung dan cara kerjanya, Anda harus melihat bantuannya test. Ketika Anda menjalankan perintah help test, Anda akan mendapatkan daftar terperinci. Daripada mereproduksi semuanya, inilah bagian tentang operator string:

      -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.

Perhatikan itu -n STRINGdan STRINGlakukan hal yang sama: mereka menguji apakah string STRINGtidak kosong.


2
Penjelasan yang bagus
Sergiy Kolodyazhnyy

1
Mungkin juga menyebutkan bahwa ini memiliki implikasi untuk variabel yang tidak dikutip yang tidak disetel, seperti ini: paste.ubuntu.com/25831047
Sergiy Kolodyazhnyy

1
@SergiyKolodyazhnyy Saya pikir mungkin lebih baik dalam jawaban yang terpisah. Variabel yang tidak disetel, atau disetel tetapi kosong, atau hanya berisi IFSspasi putih, akan melakukan itu; variabel yang berisi banyak kata dan bukannya nol menghasilkan efek lain dan dapat menyebabkan tes yang sama sekali berbeda dijalankan. String yang muncul secara harfiah dengan maksud menjadi operan hanya akan berfungsi dengan baik jika tidak mengandung spasi atau tab atau jika dikutip. Jawabannya akan menjadi jauh lebih lama dan lebih rumit jika saya membahas topik ini dengan cara yang dapat diakses. Jika Anda memutuskan untuk mengirim jawaban, silakan @ saya di sini tentang hal itu!
Eliah Kagan

@Eliah Kagan, jawaban Anda lebih lengkap dan terperinci meskipun tanggapan Ignacio Vazquez-Abrams menjawab pertanyaan saya.
Ravi Kumar

1
Saya pikir Anda kehilangan alasannya dan harus seperti ini: jika tidak, tidak [ "$var" ]akan pernah dapat digunakan sebagai ujian karena $vardapat diperluas ke -n.
R ..

12

[ -n ]ini benar karena [perintah (alias testperintah) bertindak berdasarkan jumlah argumen yang diberikan. Jika hanya diberikan argumen tunggal, hasilnya "benar" jika argumen tersebut adalah string yang tidak kosong. "-n" adalah string dengan 2 karakter, bukan kosong, oleh karena itu "true".

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.