Попытка выяснить, как преобразовать аргумент в целое число для выполнения арифметики, а затем распечатать его, скажем, для addOne.sh
:
echo $1 + 1
>>sh addOne.sh 1
prints 1 + 1
Попытка выяснить, как преобразовать аргумент в целое число для выполнения арифметики, а затем распечатать его, скажем, для addOne.sh
:
echo $1 + 1
>>sh addOne.sh 1
prints 1 + 1
Ответы:
В bash нельзя «преобразовать аргумент в целое число для выполнения арифметики». В bash переменные обрабатываются как целое число или строка в зависимости от контекста.
Чтобы выполнить арифметику, вы должны вызвать оператор арифметического расширения $((...))
. Например:
$ a=2
$ echo "$a + 1"
2 + 1
$ echo "$(($a + 1))"
3
или вообще предпочтительнее:
$ echo "$((a + 1))"
3
Вы должны знать, что bash (в отличие от ksh93, zsh или yash) выполняет только целочисленную арифметику. Если у вас есть числа с плавающей запятой (числа с десятичными числами), то есть другие инструменты, которые могут вам помочь. Например, используйте bc
:
$ b=3.14
$ echo "$(($b + 1))"
bash: 3.14 + 1: syntax error: invalid arithmetic operator (error token is ".14 + 1")
$ echo "$b + 1" | bc -l
4.14
Или вы можете использовать оболочку с арифметической поддержкой с плавающей запятой вместо bash:
zsh> echo $((3.14 + 1))
4.14
В bash
, вы можете выполнить преобразование из целого числа, используя printf -v :
printf -v int '%d\n' "$1" 2>/dev/null
Плавающее число будет преобразовано в целое число, в то время как все, что не похоже на число, будет преобразовано в 0. Возведение в степень будет усечено до числа до e
Пример:
$ printf -v int '%d\n' 123.123 2>/dev/null
$ printf '%d\n' "$int"
123
$ printf -v int '%d\n' abc 2>/dev/null
$ printf '%d\n' "$int"
0
$ printf -v int '%d\n' 1e10 2>/dev/null
$ printf '%d\n' "$int"
1
printf -v
этого можно добиться с помощью подстановки команд:int="$(printf '%d' 123.123 2>/dev/null)"
bash
вы использовали?
Подобная ситуация возникла недавно при разработке сценариев bash для работы в среде Linux и OSX. Результат одной команды в OSX вернул строку, содержащую код результата; то есть " 0"
. Конечно, это не удалось проверить правильно в следующем случае:
if [[ $targetCnt != 0 ]]; then...
Решение состояло в том, чтобы принудительно (то есть, «преобразовать») результат в целое число, аналогично тому, что @ John1024 ответил выше, чтобы он работал как ожидалось:
targetCnt=$(($targetCnt + 0))
if [[ $targetCnt != 0 ]]; then...
==
и т. д. [[
(также [
известный как test
) сделать сравнение строк. Существуют разные операторы для арифметического сравнения, например [[ $targetcnt -ne 0 ]]
; см. man-страницу (или информацию) под условными выражениями. Для того, чтобы обрезать пробелы, вы можете использовать [
расширение без [ $targetcnt == 0 ]
кавычек, чтобы получить разделение слов по умолчанию (НЕ сделано в [[
), но в целом такой подход приводит вас к опасности.
заботьтесь о цветовых кодах, даже в trace ( -x
) они не появятся, что выдаст его, так это то, что строка, которая должна быть числом, заключена в кавычки независимо от того, как вы ее печатаете.
$((var+var))
fail, даже хотя если вы echo
или printf
оба варя они одинаковы. Я не знаю, как исправить это, поскольку я смог исправить это только путем отключения цветовых кодов в источнике вывода. Чтобы обнаружить его в журналах трассировки, вы увидите, что переменная, для которой var='0'
var=0
sed
если вы не можете его отключить
printf "1 + %s\n" $1 won't do ?