bash: Я зламав [[<]]


14

Я писав баш сценарій і раптом така поведінка почалася:

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

але -ltпрацює добре:

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

я випадково <якось переписав ?

ось сценарій, який я написав для перевірки такої поведінки:

#!/bin/bash

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

    echo
done

ось вихід:

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

зміни <до -ltв сценарії дає нормальний вихід ( 5 10показує вгору, наприклад).

Перезавантаження нічого не змінило.

Моя версія bash - це GNU bash, версія 4.3.42 (1) -release (x86_64-pc-linux-gnu). Я на Ubuntu 15.10. Я не знаю, яка інша інформація тут є актуальною.


16
з <операцією ви здійснюєте порівняння рядків, тоді як -ltоператор - це числове порівняння. Якщо ви подивитеся на перелічені результати, ви зрозумієте це. Число 2 менше, ніж 10, за алфавітом, навпаки.
Мельбурслан

Відповіді:


51

З bashчоловічої сторінки.

При використанні з [[, оператори <і> сортують лексикографічно, використовуючи поточну локаль.

З виводу, здається, працює як задумано.


35
Іншими словами, прочитайте сторінку man, перш ніж припустити, що знайшли помилку. ;)
Wildcard

Правда. Можливо, сценарій, над яким я спочатку працював, почав насправді працювати «правильно» (як у разі відмови [[$ myvar <13]]), коли я помітив таку поведінку. Чи можу я зараз зробити це питання? Чи змінюємо ми на цьому сайті назву, щоб включити [вирішено] чи щось таке? Чи варто все-таки змінити назву на щось більш описове?
равлик на квест

2
Ні, не змінюйте назву питання. Позначення поруч із цією відповіддю достатньо, щоб вказати, що питання вирішено.
saiarcot895

14
@Wildcard ОП не припускає, що знайшли помилку. Вони прямо говорять про те, що, можливо, вони щось зробили, щоб змінити поведінку. Навіть назва передбачає стільки ж!
jpmc26

5

Як щодо:

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

Відповідно до http://www.tldp.org/LDP/abs/html/dblparens.html

Як і команда let, конструкція ((...)) дозволяє арифметичне розширення та оцінку. У своєму найпростішому вигляді a = $ ((5 + 3)) встановив би 5 + 3, або 8. Однак ця конструкція з подвійними дужками також є механізмом, що дозволяє керувати змінами в Bash-стилі, наприклад, , ((var ++)).


2
Ви пропускаєте суть питання - це не "як я можу порівняти ці значення?" але "чому він поводиться так, як це робить?".
guntbert

7
На це вже відповіли. Але оскільки він хотів використовувати арифметичний вираз, можливо, варто зазначити, що існують конструкції, які дозволяють використовувати ті, що знаходяться в оболонці.
ПолСмекер

3

По-перше, [[ це не POSIX і його слід уникати.

По-друге, якщо ви хочете використовувати <як частину арифметичного тесту, ви можете це зробити, але з різним синтаксисом:

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

Або:

if expr 2 '<' 13
then
  echo '2 is less than 13'
else
  echo '2 is greater or equal to 13'
fi
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.