При разыменовании переменной в bash
, вы должны использовать $
знак. Тем не менее, кажется, что следующее работает просто отлично:
x=5
[[ x -gt 2 ]]
Кто-нибудь может объяснить это?
Редактировать: (подробнее)
Я имею в виду, как и почему команда [[]] разыменовывает мою переменную x без знака $. И да, если x = 1, оператор оценивается как ложный (возвращаемый статус 1)
bash
bash-expansion
гость
источник
источник
x=1
последуете[[ x -gt 2]]
?Ответы:
Причина в том, что
-eq
силы арифметической оценки аргументов.Арифметический оператор:
-eq
,-gt
,-lt
,-ge
,-le
и-ne
внутри[[ ]]
(в KSH, Zsh и Баш) средство для автоматического расширения имен переменных , как и в языке С, не нужно для ведущего$
.Для подтверждения мы должны заглянуть в исходный код bash. Руководство не предлагает прямого подтверждения.
Внутри
test.c
обработки арифметические операторы попадают в эту функцию:Где
s
иt
оба операнда. Операнды передаются этой функции:Функция
evalexp
определена внутриexpr.c
, которая имеет этот заголовок:Итак, да, обе стороны арифметического оператора (напрямую) попадают в оценку арифметического выражения. Напрямую, нет, но если нет.
На практике с:
Оба из этого терпят неудачу:
Что правильно,
x
не расширяется иx
не равно числу.Тем не мение:
Переменная named
x
раскрывается (даже без $).Это не происходит для
[…]
zsh или bash (это происходит для ksh).Это то же самое, что происходит внутри
$((…))
:И, пожалуйста, поймите, что это (очень) рекурсивно (кроме дефиса и тире):
A 😮
И довольно рискованно
Синтаксической ошибки можно легко избежать:
Как говорится: дезинфицируйте ваш вклад
конец 😮
И (более старый) внешний
/usr/bin/test
(не встроенныйtest
), и еще более старый, а также внешнийexpr
не расширяют выражения только целыми числами (и, по-видимому, только десятичными):источник
[[
ключевым словом, операторы и операнды обнаруживаются при чтении команды, а не после раскрытия. Таким образом ,[[
можно рассматривать-eq
в более умном , чем, скажем,[
. Но вот что мне интересно: где мы можем найти документацию о логике, которую использует bash для интерпретации составных команд? Это не выглядит для меня очевидным, и я, очевидно, не могу найти удовлетворительных объяснений вman
илиinfo bash
.test
Операнды численных сравнений
-eq
,-gt
,-lt
,-ge
,-le
и-ne
принимаются в качестве арифметических выражений. С некоторыми ограничениями, они по-прежнему должны быть словами из одной оболочки.Поведение имен переменных в арифметическом выражении описано в Shell Arithmetic :
а также:
Но я не могу найти ту часть документации, в которой говорится, что числовые сравнения принимают арифметические выражения. Он не описан в Условных конструкциях в разделе
[[
и не описан в Условных выражениях Bash .Но, экспериментально, кажется, работает как сказано выше.
Итак, такие вещи работают:
это тоже (значение переменной оценивается):
Но это не так; это не одно слово оболочки при
[[ .. ]]
разборе, поэтому в условном выражении есть синтаксическая ошибка:В других арифметических контекстах нет необходимости, чтобы выражение было без пробелов. Это печатает
999
, поскольку скобки однозначно разграничивают арифметическое выражение в индексе:С другой стороны,
=
сравнение является сопоставлением с шаблоном и не включает арифметику и автоматическое расширение переменных, выполняемое в арифметическом контексте (условные конструкции):Так что это неверно, поскольку строки явно разные:
как это, даже если числовые значения одинаковы:
и здесь тоже сравниваются строки (
x
и6
), они разные:Это расширило бы переменную, так что это правда:
источник
arg1 OP arg2
говорится, что аргументы могут быть положительными или отрицательными целыми числами, что, как я предполагаю, предполагает, что они рассматриваются как арифметические выражения. Смущает, это также подразумевает, что они не могут быть нулем. :)[
, и там они не являются арифметическими выражениями. Вместо этого Баш жалуется на нецелые числа.[
- это внешняя команда, она не имеет доступа к переменным оболочки. Он часто оптимизируется с помощью встроенной команды, но ведет себя так же.[
же, как и[[
. Даже при[
этом операнды-eq
и друзья должны быть целыми числами, поэтому описание также применимо. Принятие «должны быть целыми числами» означает «интерпретируются как арифметические выражения» не применимо в обоих случаях. (Возможно, по крайней мере, отчасти из-за того[
, что вы действуете как обычная команда, как вы говорите.)Да, ваши наблюдения верны, расширение переменных выполняется для выражений в двойных скобках
[[ ]]
, поэтому вам не нужно ставить$
перед именем переменной.Это прямо указано в
bash
руководстве:Обратите внимание, что это не версия с одной скобкой
[ ]
, так как[
это не ключевое слово оболочки (синтаксис), а команда (в bash она встроена, другие оболочки могут использовать внешние, выровненные для тестирования).источник
(x=1; [[ $x = 1 ]]; echo $?)
возврат0
,(x=1; [[ x = 1 ]]; echo $?)
возврат1
, т.е. расширение параметров не выполняетсяx
при сравнении строк. Это поведение выглядит как арифметическая оценка, вызванная арифметическим расширением, то есть тем, что происходит в(x=1; echo $((x+1)))
. (Об арифметической оценкеman bash
говорится, что «Внутри выражения на переменные оболочки также можно ссылаться по имени без использования синтаксиса расширения параметров).-gt
оператор ожидает число, поэтому все выражение переоценивается так, как будто оно внутри(())
, с другой стороны,==
ожидает строки, поэтому вместо этого запускается функция сопоставления с образцом. Я не копался в исходном коде, но звучит разумно.[
это оболочка, встроенная в bash