Сравнение целых чисел: арифметическое выражение или условное выражение


20

В Bash два целых числа можно сравнить с помощью условного выражения

arg1 OP arg2

OP является одним из -eq, -ne, -lt, -le, -gt, или -ge. Эти арифметические бинарные операторы возвращают true, если arg1 равно, не равно, меньше, меньше или равно, больше или больше или равно arg2 , соответственно. Arg1 и arg2 могут быть положительными или отрицательными целыми числами.

или арифметическое выражение:

<= >= < > сравнение

== != равенство и неравенство

Почему у нас есть два разных способа сравнения двух целых чисел? Когда использовать что?

Например, [[ 3 -lt 2 ]]использует условное выражение и (( 3 < 2 ))использует арифметическое выражение. Оба возвращают 0, когда сравнение истинно

При сравнении двух целых чисел всегда можно использовать эти два метода взаимозаменяемо? Если да, почему у Bash есть два метода, а не один?


1
= != < <= > >=сравнить строки . 1 -eq 01но 1 != 01и 8 -lt 42но8 > 42
dave_thompson_085

Они перегружены в арифметических выражениях.
Тим

1
вам придется искать в журнале изменений bash, чтобы узнать, когда была добавлена ​​каждая функция. Я подозреваю, что арифметические выражения были добавлены намного позже, чем команда test.
Гленн Джекман

Я не спрашиваю о сравнении строк. @muru.
Тим

Ответы:


28

Да, у нас есть два разных способа сравнения двух целых чисел.

Похоже, что эти факты не получили широкого распространения на этом форуме:

  1. Внутри идиомы [ ]операторы для арифметического сравнения -eq, -ne, -lt, -le, -gtи -ge.

    Поскольку они также находятся внутри команды тестирования и внутри [[ ]].

    Да в этой идиомы, =, <и т.д. строковые операторы.

  2. Внутри идиомы (( ))операторы для арифметического сравнения ==, !=, <, <=, >, и >=.

    Нет, это не «Арифметическое расширение» (которое начинается с $), поскольку $(( )). Это определяется как «Составная команда» в man bash.

    Да, он следует тем же правилам (внутри) «Арифметического расширения», но не имеет выходных данных, только выходное значение. Это можно использовать так:

if (( 2 > 1 )); then ...

Почему у нас есть два разных способа сравнения двух целых чисел?

Я предполагаю, что последний (( ))был разработан как более простой способ выполнения арифметических тестов. Это почти так же, как, $(( ))но просто не имеет выхода.

Почему два? Ну так же , как , почему у нас есть два printf(внешняя и встроенная) или четыре испытания (внешняя test, встроенная команда test, [и [[). Так растут раковины, улучшая некоторые области за один год, улучшая другие в следующем году.

Когда использовать что?

Это очень сложный вопрос, потому что не должно быть эффективной разницы. Конечно, есть некоторые различия в способе [ ]работы и (( ))работы внутри страны, но: что лучше сравнить два целых числа? Кто-нибудь!.

При сравнении двух целых чисел всегда можно использовать эти два метода взаимозаменяемо?

На два номера я вынужден сказать да.
Но для переменных, расширений, математических операций могут быть ключевые различия, которые должны благоприятствовать тем или иным. Не могу сказать, что абсолютно оба равны. Например, он (( ))может выполнить несколько математических операций в последовательности:

if (( a=1, b=2, c=a+b*b )); then echo "$c"; fi

Если да, почему у Bash есть два метода, а не один?

Если оба полезны, почему бы и нет?


1
=является присваиванием и ==является сравнением в арифметических разложениях. Вопрос цитирует это правильно. Но ответ неверный.
выступление

12

Исторически testкоманда существовала первой (по крайней мере, еще в седьмом издании Unix в 1979 году). Раньше операторы =и !=сравнение строк, и -eq, -ne, -ltи т.д. для сравнения чисел. Например, test 0 = 00ложно, но test 0 -eq 00верно. Я не знаю, почему был выбран этот синтаксис, но, возможно, это было сделано для того, чтобы избежать использования <и >, которое оболочка проанализировала бы как операторы перенаправления. Через testнесколько лет команда получила другой синтаксис: [ … ]эквивалентно test ….

[[ … ]]Условный синтаксис, внутри которого <и >может быть использован в качестве операторов , не цитируя, был добавлен позже, в KSH. Он сохранял обратную совместимость с [ … ], поэтому он использовал те же операторы, но добавил <и >для сравнения строк (например, [[ 9 > 10 ]]но [[ 9 -lt 10 ]]). Для получения дополнительной информации см. Использование одинарной или двойной скобки - bash

Арифметические выражения также появились позже, чем testкоманда, в оболочке Korn , в какое-то время в 1980-х годах. Они следовали синтаксису языка Си, который был очень популярен в кругах Unix. Таким образом, они использовали операторы Си: ==для равенства, <=для менее или равных и т. Д.

Unix Seventh Edition не имел арифметических выражений, но в нем была exprкоманда , которая также реализовала C-подобный синтаксис для целочисленных операций, включая операторы сравнения. В сценарии оболочки символы <и >должны быть заключены в кавычки, чтобы защитить их от оболочки, например if expr 1 \< 2; …эквивалентно if test 1 -lt 2; …. Добавление арифметических выражений в оболочку в большинстве случаев exprустарело, поэтому сегодня это не очень хорошо известно.

В сценарии sh вы обычно используете арифметические выражения для вычисления целого значения и [ … ]сравнения целых чисел.

if [ "$((x + y))" -lt "$z" ]; then 

В сценариях ksh, bash или zsh вы можете использовать ((…))оба варианта.

if ((x + y < z)); then 

[[ … ]]Форма полезна , если вы хотите использовать условные с участием других , чем целые вещей.


1

Согласно справочной странице теста, = и! = Используются для сравнения строк, а выражения -eq, -gt, -lt, -ge, -le и -ne являются целочисленными сравнениями. Я всегда следовал этому соглашению при написании сценариев оболочки, и он всегда работает. Помните, что если в выражении есть переменные, вам может потребоваться заключить их в кавычки, чтобы избежать нулевого сравнения.

На бумаге мы проводим сравнение строк / чисел без особых раздумий. Компьютер, с другой стороны, не знает, является ли 987 числом или строкой символов. Вам нужно, чтобы разные операторы сообщали компьютеру, что делать, чтобы получить правильный результат. Существует некоторая дополнительная информация здесь , что объясняет некоторые из истории. По сути, переменные нетипизированы и остались такими для исторической совместимости.


В моем посте = и !=приведены арифметические операторы, тогда как на man-странице testпоказаны только операторы условных выражений.
Тим
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.