Я пытаюсь отформатировать ваш вопрос, но он остается каким-то неясным. printf "1 + %s\n" $1 won't do ?
Архемар
Ответы:
89
В bash нельзя «преобразовать аргумент в целое число для выполнения арифметики». В bash переменные обрабатываются как целое число или строка в зависимости от контекста.
Чтобы выполнить арифметику, вы должны вызвать оператор арифметического расширения $((...)). Например:
$ a=2
$ echo "$a + 1"2+1
$ echo "$(($a + 1))"3
или вообще предпочтительнее:
$ echo "$((a + 1))"3
Вы должны знать, что bash (в отличие от ksh93, zsh или yash) выполняет только целочисленную арифметику. Если у вас есть числа с плавающей запятой (числа с десятичными числами), то есть другие инструменты, которые могут вам помочь. Например, используйте bc:
Использование $ (()) или (()) небезопасно, если вы не знаете, что это за строки (например, пользовательский ввод). Учтите это: foo = foo ((foo + = 0)) Это приведет к сбою скрипта при попытке рекурсивной оценки foo. То же самое с: foo = foo foo = $ ((foo + 0))
В bash, вы можете выполнить преобразование из целого числа, используя printf -v :
printf -v int '%d\n'"$1"2>/dev/null
Плавающее число будет преобразовано в целое число, в то время как все, что не похоже на число, будет преобразовано в 0. Возведение в степень будет усечено до числа до e
Пример:
$ printf -v int '%d\n'123.1232>/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'1e102>/dev/null
$ printf '%d\n'"$int"1
В других оболочках без printf -vэтого можно добиться с помощью подстановки команд:int="$(printf '%d' 123.123 2>/dev/null)"
Адриан Гюнтер
2
Это не работает в Bash.
Майкл Мартинес
@MichaelMartinez ты уверен? Какую версию bashвы использовали?
Cuonglm
GNU bash, версия 4.2.46 (1) -релиз (x86_64-redhat-linux-gnu)
Майкл Мартинес
5
Подобная ситуация возникла недавно при разработке сценариев bash для работы в среде Linux и OSX. Результат одной команды в OSX вернул строку, содержащую код результата; то есть " 0". Конечно, это не удалось проверить правильно в следующем случае:
if[[ $targetCnt !=0]];then...
Решение состояло в том, чтобы принудительно (то есть, «преобразовать») результат в целое число, аналогично тому, что @ John1024 ответил выше, чтобы он работал как ожидалось:
==и т. д. [[(также [известный как test) сделать сравнение строк. Существуют разные операторы для арифметического сравнения, например [[ $targetcnt -ne 0 ]]; см. man-страницу (или информацию) под условными выражениями. Для того, чтобы обрезать пробелы, вы можете использовать [расширение без [ $targetcnt == 0 ]кавычек, чтобы получить разделение слов по умолчанию (НЕ сделано в [[), но в целом такой подход приводит вас к опасности.
dave_thompson_085
-2
заботьтесь о цветовых кодах, даже в trace ( -x) они не появятся, что выдаст его, так это то, что строка, которая должна быть числом, заключена в кавычки независимо от того, как вы ее печатаете.
Отклонено, так как я нахожу ваш ответ немного неясным. Возможно, вы могли бы добавить, что скрипт должен быть исправлен?
Time4Tea
это был лучший ответ при поиске bash + integer + string, поэтому я добавил связанную с ним информацию, которая не была включена в ответы, то есть, когда строки заключены в коды цветов, может быть неясно, почему такие операции, как $((var+var))fail, даже хотя если вы echoили printfоба варя они одинаковы. Я не знаю, как исправить это, поскольку я смог исправить это только путем отключения цветовых кодов в источнике вывода. Чтобы обнаружить его в журналах трассировки, вы увидите, что переменная, для которой var='0'var=0
возникла ошибка,
Что вы можете сделать, так это убедиться, что на выходе нет цветовых кодов, sedесли вы не можете его отключить
printf "1 + %s\n" $1 won't do ?
Ответы:
В bash нельзя «преобразовать аргумент в целое число для выполнения арифметики». В bash переменные обрабатываются как целое число или строка в зависимости от контекста.
Чтобы выполнить арифметику, вы должны вызвать оператор арифметического расширения
$((...))
. Например:или вообще предпочтительнее:
Вы должны знать, что bash (в отличие от ksh93, zsh или yash) выполняет только целочисленную арифметику. Если у вас есть числа с плавающей запятой (числа с десятичными числами), то есть другие инструменты, которые могут вам помочь. Например, используйте
bc
:Или вы можете использовать оболочку с арифметической поддержкой с плавающей запятой вместо bash:
источник
Другой способ, вы можете использовать
expr
Пример:
источник
В
bash
, вы можете выполнить преобразование из целого числа, используя printf -v :Плавающее число будет преобразовано в целое число, в то время как все, что не похоже на число, будет преобразовано в 0. Возведение в степень будет усечено до числа до
e
Пример:
источник
printf -v
этого можно добиться с помощью подстановки команд:int="$(printf '%d' 123.123 2>/dev/null)"
bash
вы использовали?Подобная ситуация возникла недавно при разработке сценариев bash для работы в среде Linux и OSX. Результат одной команды в OSX вернул строку, содержащую код результата; то есть
" 0"
. Конечно, это не удалось проверить правильно в следующем случае:Решение состояло в том, чтобы принудительно (то есть, «преобразовать») результат в целое число, аналогично тому, что @ John1024 ответил выше, чтобы он работал как ожидалось:
источник
==
и т. д.[[
(также[
известный какtest
) сделать сравнение строк. Существуют разные операторы для арифметического сравнения, например[[ $targetcnt -ne 0 ]]
; см. man-страницу (или информацию) под условными выражениями. Для того, чтобы обрезать пробелы, вы можете использовать[
расширение без[ $targetcnt == 0 ]
кавычек, чтобы получить разделение слов по умолчанию (НЕ сделано в[[
), но в целом такой подход приводит вас к опасности.заботьтесь о цветовых кодах, даже в trace (
-x
) они не появятся, что выдаст его, так это то, что строка, которая должна быть числом, заключена в кавычки независимо от того, как вы ее печатаете.источник
$((var+var))
fail, даже хотя если выecho
илиprintf
оба варя они одинаковы. Я не знаю, как исправить это, поскольку я смог исправить это только путем отключения цветовых кодов в источнике вывода. Чтобы обнаружить его в журналах трассировки, вы увидите, что переменная, для которойvar='0'
var=0
sed
если вы не можете его отключить