Баш: я сломал [[<]]

14

Я писал сценарий bash, и вдруг это поведение началось:

[[ 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) -релиз (x86_64-pc-linux-gnu). Я на Ubuntu 15.10. Я не знаю, какая другая информация уместна здесь.

Улитка-на-квест
источник
16
с <операцией вы выполняете сравнение строк, тогда как -ltоператором является сравнение чисел. Если вы посмотрите на результаты, которые вы перечислили, вы поймете это. Численно 2 меньше 10, в алфавитном порядке, наоборот.
MelBurslan

Ответы:

51

Со bashстраницы руководства .

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

Судя по выводу, он работает так, как задумано.

Стив
источник
35
Другими словами, прочитайте справочную страницу, прежде чем предположить, что нашли ошибку. ;)
Подстановочный
Правда. Возможно, скрипт, над которым я первоначально работал, начал работать «правильно» (как в случае сбоя [[$ 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. Однако эта конструкция с двойными скобками также является механизмом, позволяющим, например, манипулировать переменными в стиле C в Bash, например , ((var ++)).

PaulSmecker
источник
2
Вы упускаете суть вопроса - это не "как я могу сравнить эти значения?" но "почему он ведет себя так, как делает?"
Гюнтберт
7
На это уже ответили. Но так как он хотел использовать арифметическое выражение, возможно, стоит отметить, что существуют конструкции, которые позволяют использовать их в оболочке.
PaulSmecker
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
Стивен Пенни
источник