Как вы определяете «полностью» 64 -бит?
% file /usr/bin/perl
/usr/bin/perl: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit executable x86_64] [i386:Mach-O executable i386]
/usr/bin/perl (for architecture x86_64): Mach-O 64-bit executable x86_64
/usr/bin/perl (for architecture i386): Mach-O executable i386
% sw_vers
ProductName: Mac OS X
ProductVersion: 10.13.5
BuildVersion: 17F77
! [ "$var" -gt 0 ]
и [ ! "$var" -gt 0 ]
не должны иметь значения для текущих оболочек и утилит, если нет ошибок.
Но обратите внимание, что вы написали if ! [ $var -gt 0 ]
и if [ ! $var -gt 0 ]
без кавычек вокруг $var
и что имеет значение !
Это могло бы сломаться, если бы $var
было пустым или содержало пробелы. Вы получите, например. if ! [ -gt 0 ]
, где тест [
напечатает сообщение об ошибке и вернет ложный код выхода 2. Затем он будет инвертирован !
, и условие в целом будет истинным!
$ var=
$ if ! [ $var -gt 0 ]; then echo yes; fi
bash: [: -gt: unary operator expected
yes
В этом конкретном контексте [ ! $var -gt 0 ]
можно рассматривать как более безопасный, поскольку возврат ложной ошибки останется ложным, а ветвь не будет выполнена. Здесь непосредственная проблема заключается в отсутствии кавычек, и это легко исправить.
О кавычках см.:Когда необходимо двойное -цитирование?
Однако, даже помимо проблемы цитирования, не-числовые значения в $var
также давали бы ошибку из [
и делали бы условие ложным. Из-за этого вы должны заранее проверить правильность входных данных или иным образом обработать эту возможность. В некоторых случаях правильное действие в случае ошибки может состоять в том, чтобы выбрать ветвь, например. если он содержал ошибку выхода. К сожалению, у оболочки нет хорошего способа обнаружения ошибок, так как нет никаких исключений или чего-то подобного. Чтобы отличить ошибку от ложного результата, необработанное значение в $?
необходимо сохранить и просмотреть.
Или тест можно написать так, чтобы случай ошибки совпадал с соответствующим результатом. Например, здесь тест написан с дополнительным отрицанием вместо [ "$1" -le 0 ]
, но это имеет то преимущество, что недопустимый ввод вызовет выход по ошибке. Это работает только с !
снаружи [
.
$ cat foo.sh
#!/bin/bash
if ! [ "$1" -gt 0 ]; then
echo "invalid input '$1'"
exit 1
fi
echo "doing work on '$1'"
$ bash foo.sh
foo.sh: line 3: [: : integer expression expected
invalid input ''
Вариации значений переменной и различные тесты в матрице:
test \ $n | '0' '1' 'x' -------------------+------------------------------------ [ "$n" -le 0 ] | truthy falsy falsy (w/error) [ ! "$n" -gt 0 ] | truthy falsy falsy (w/error) ! [ "$n" -gt 0 ] | truthy falsy truthy (w/error)
Возможно, в какой-то мере это связано с тем, что в былые времена версии [
, как известно, путались, когда операнды в тесте выглядели как операторы. Например. с чем-то вроде [ ! = x ]
!
может быть воспринято как отрицание, и выражение в целом не может быть проанализировано. Можно опасаться, что размещение !
внутри [
может усугубить эту проблему, но я не знаю, произошло бы это на практике. В любом случае версии [
, соответствующие POSIX -, должны быть защищены от этого, по крайней мере, до тех пор, пока вы не используете -a
и -o
.
См.:Какова цель добавления префикса с обеих сторон сравнения переменных оболочки к строковому литералу? , особенно отличный ответ Стефана (, из которого я взял [ ! = x ]
пример ).
Это имеет значение, только если вы заботитесь о том, что оценивает !
, что вы можете сделать, если вы принимаете во внимание сбои в утилите [
, (, например. $var
на самом деле не является целым числом, и в этом случае утилита [
потерпит неудачу, и ее статус выхода будет не -нулем, то есть не потому, что тест оценивается как false , а потому, что утилита не удалась выполнить тест ).
В if [ ! "$var" -gt 0 ]; then...; fi
!
является аргументом для [
и, следовательно, будет оцениваться утилитой [
, заставляя ее внутренне отрицать смысл теста перед завершением с соответствующим статусом выхода. (Если $var
не является целым числом, тест завершится неудачно, и переход не будет выполнен.)
В if ! [ "$var" -gt 0 ]; then...; fi
оболочка будет отрицать (хорошо, переключать между 0 и не -нулем )статус выхода утилиты [
перед использованием его для оператора if
. (Если $var
не является целым числом, тест завершится ошибкой, оболочка отменит не-нулевой статус выхода и интерпретирует его как true , и будет выполнено ветвление.)
Для этого простого теста я, вероятно, переписал бы тест как [ "$var" -le 0 ]
для простоты чтения и понимания кода и, если необходимо, использовал проверку $var
как целое число.
Да, это имеет значение.
Если вы поместите !
вне [... ]
, то любая ошибка будет проигнорирована:
var=nono
if ! [ "$var" -gt 0 ]; then echo YES; fi
bash: [: 0.1: integer expression expected
YES
if [ ! "$var" -gt 0 ]; then echo YES; fi
bash: [: 0.1: integer expression expected
Это потому, что if ! command; then...
будет соответствовать, когда статус выхода command
не равен -нулю,а команда [ expr ]
будет иметь ненулевой статус выхода, отличный от -, как в случае ошибки, так и в случае, когда expr
оценивается как ложное.
Только в ksh (НЕ в bash )два вида похожи, потому что в ksh числовая переменная, не являющаяся -, будет рассматриваться как 0
в этом контексте, а не как ошибка.