bash: Saya bangkrut [[<]]

14

Saya sedang menulis skrip bash dan tiba-tiba perilaku ini dimulai:

[[ 1 < 2 ]]; echo $?  # outputs 0
[[ 2 < 13 ]]; echo $? # outputs 1

tapi -ltbekerja dengan baik:

[[ 1 -lt 2 ]]; echo $?  # outputs 0
[[ 2 -lt 13 ]]; echo $? # outputs 0

Apakah saya <entah bagaimana secara tidak sengaja menimpa ?

berikut ini skrip yang saya tulis untuk menguji perilaku ini:

#!/bin/bash

for a in {1..5}
do
    for b in {1..20}
    do
        [[ $a < $b ]] && echo $a $b
    done

    echo
done

di sini adalah output:

1 2
1 3
1 4
1 5
1 6
1 7
1 8
1 9
1 10
1 11
1 12
1 13
1 14
1 15
1 16
1 17
1 18
1 19
1 20

2 3
2 4
2 5
2 6
2 7
2 8
2 9
2 20

3 4
3 5
3 6
3 7
3 8
3 9

4 5
4 6
4 7
4 8
4 9

5 6
5 7
5 8
5 9

mengubah <ke -ltdalam skrip memberikan output normal ( 5 10muncul misalnya).

Mem-boot ulang tidak mengubah apa pun.

Versi bash saya adalah GNU bash, versi 4.3.42 (1) -release (x86_64-pc-linux-gnu). Saya di Ubuntu 15.10. Saya tidak tahu informasi apa yang relevan di sini.

bekicot saat bepergian
sumber
16
dengan <operasi, Anda membuat perbandingan string, sedangkan -ltoperator perbandingan numerik, Jika Anda melihat hasil yang telah Anda daftarkan, Anda akan menyadarinya. Secara numerik 2 kurang dari 10, menurut abjad, sebaliknya.
MelBurslan

Jawaban:

51

Dari bashhalaman manual.

Saat digunakan dengan [[, operator <dan> mengurutkan secara leksikografis menggunakan lokal saat ini.

Dari output, tampaknya berfungsi seperti yang dirancang.

steve
sumber
35
Dengan kata lain, baca halaman manual sebelum Anda menganggap Anda telah menemukan bug. ;)
Wildcard
Benar. Mungkin skrip yang semula saya kerjakan mulai benar-benar berfungsi 'dengan benar' (seperti pada kegagalan [[$ myvar <13]]) ketika saya memperhatikan perilaku ini. Apakah ada yang harus saya lakukan untuk pertanyaan ini sekarang? Apakah kita di situs ini mengubah judul untuk memasukkan [diselesaikan] atau sesuatu? Haruskah judul diubah pula menjadi sesuatu yang lebih deskriptif?
bekicot
2
Tidak, jangan ubah judul pertanyaan. Tanda centang di sebelah jawaban ini cukup untuk menunjukkan bahwa pertanyaan telah diselesaikan.
saiarcot895
14
@ Kartu Memori OP tidak menganggap mereka menemukan bug. Mereka secara eksplisit menyarankan bahwa mungkin mereka telah melakukan sesuatu untuk mengubah perilaku. Bahkan judulnya juga banyak!
jpmc26
5

Bagaimana tentang:

for a in {1..5}; 
do     
  for b in {1..20};     
  do         
    (( $a < $b )) && echo $a $b
  done      
  echo
done

Menurut http://www.tldp.org/LDP/abs/html/dblparens.html

Mirip dengan perintah let, konstruk ((...)) memungkinkan ekspansi dan evaluasi aritmatika. Dalam bentuknya yang paling sederhana, a = $ ((5 + 3)) akan menetapkan menjadi 5 + 3, atau 8. Namun, konstruk tanda kurung ganda ini juga merupakan mekanisme untuk memungkinkan manipulasi gaya-C dari variabel dalam Bash, misalnya , ((var ++)).

PaulSmecker
sumber
2
Anda melewatkan inti pertanyaan - bukan "bagaimana saya bisa membandingkan nilai-nilai itu?" tetapi "mengapa itu berperilaku seperti itu?".
guntbert
7
Ini sudah dijawab. Tetapi karena dia ingin menggunakan ekspresi aritmatika, mungkin ada baiknya menunjukkan bahwa ada konstruksi yang memungkinkan Anda untuk menggunakan yang ada di shell.
PaulSmecker
3

Pertama, [[ bukan POSIX dan harus dihindari.

Kedua, jika Anda ingin menggunakan <sebagai bagian dari tes aritmatika Anda dapat melakukan ini, tetapi dengan sintaks yang berbeda:

if [ $((2 < 13)) = 1 ]
then
  echo '2 is less than 13'
else
  echo '2 is greater or equal to 13'
fi

Atau:

if expr 2 '<' 13
then
  echo '2 is less than 13'
else
  echo '2 is greater or equal to 13'
fi
Steven Penny
sumber