Как увеличить значение переменной в bash?

Я попытался увеличить числовую переменную, используя как var = $ var + 1, так и var = ($ var + 1) без успеха. Переменная - это число, хотя bash, похоже, читает его как строку.

Версия Bash 4.2.45 (1) -release (x86_64-pc-linux-gnu) на Ubuntu 13.10.

439 голосов | спросил user221744 3 TueEurope/Moscow2013-12-03T20:34:26+04:00Europe/Moscow12bEurope/MoscowTue, 03 Dec 2013 20:34:26 +0400 2013, 20:34:26

7 ответов


702

Существует несколько способов увеличения переменной в bash, но то, что вы пробовали, неверно.

Вы можете использовать, например, арифметическое расширение :

вар = $ ((вар + 1))
((Переменная = переменная + 1))
((VAR + = 1))
((Вар ++))

Или вы можете использовать let :

let "var = var + 1"
пусть "var + = 1"
пусть "var ++"

См. также: http://tldp.org/LDP/abs/html/dblparens .html .

ответил Radu Rădeanu 3 TueEurope/Moscow2013-12-03T20:39:13+04:00Europe/Moscow12bEurope/MoscowTue, 03 Dec 2013 20:39:13 +0400 2013, 20:39:13
93
var = $ ((var + 1))

Арифметика в bash использует синтаксис $ ((...)).

ответил Paul Tanzini 3 TueEurope/Moscow2013-12-03T20:38:03+04:00Europe/Moscow12bEurope/MoscowTue, 03 Dec 2013 20:38:03 +0400 2013, 20:38:03
59

Анализ производительности различных опций

Благодаря ответу Radu Rădeanu , который предоставляет следующие способы увеличения переменной в bash:

вар = $ ((вар + 1))
((Переменная = переменная + 1))
((VAR + = 1))
((Вар ++))
пусть "var = var + 1"
пусть "var + = 1"
пусть "var ++"

Есть и другие способы. Например, посмотрите другие ответы на этот вопрос.

let var ++
вар = $ ((вар ++))
((Вар ++))
{
    declare -i var
    переменная = переменная + 1
    вар + 1 =
}
{
    = 0
    i = $ (expr $ i + 1)
}

Имея так много вариантов, вы можете ответить на эти два вопроса:

  1. Есть ли разница в производительности между ними?
  2. Если так, что лучше всего работает?

Инкрементальный код проверки производительности:

#! /Bin /Баш

# Чтобы сосредоточиться исключительно на производительности каждого типа приращения
#, мы должны исключить выполнение bash, когда циклы из
# эффективность измерение. Итак, приступим к индивидуальным сценариям, которые
# increment $ i по-своему.

# Объявите i как целое число для тестов 12 и 13.
эхо> t12 'declare -i i; I = I + 1'
эхо> t13 'declare -i i; I + = 1'
# Установите i для теста 14.
эхо> t14 'i = 0; i = $ (expr $ i + 1) '

х = 100000
while ((x--)); делать
    эхо> t0 'i = $ ((i + 1))'
    эхо> t1 'i = $ ((i ++))'
    эхо> t2 '((i = i + 1))'
    эхо> t3 '((i + = 1))'
    эхо> t4 '((i ++))'
    эхо> t5 '((++ i))'
    эхо> t6 'let "i = i + 1"'
    эхо> t7 'let "i + = 1"'
    эхо> t8 'let "i ++"'
    эхо> t9 'пусть i = i + 1'
    эхо> t10 'пусть i + = 1'
    эхо> t11 'let i ++'
    эхо> t12 'i = i + 1'
    эхо> t13 'i + = 1'
    эхо> t14 'i = $ (expr $ i + 1)'
сделанный

для сценария в t0 t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t11 t12 t13 t14; делать
    line1 = "$ (head -1" $ script ")"
    printf "% -24s" "$ line1"
    {time bash "$ script"; } | & Пользователь grep
    # Поскольку stderr отправляется в grep выше, это подтвердит
    # нет ошибок при запуске команды:
    eval "$ line1"
    rm "$ script"
сделанный

Результаты:

i = $ ((i + 1)) пользователь 0m0.992s
i = $ ((i ++)) пользователь 0m0.964s
((i = i + 1)) пользователь 0m0.760s
((i + = 1)) пользователь 0m0.700s
((i ++)) пользователь 0m0.644s
((++ i)) пользователь 0m0.556s
пусть «i = i + 1» пользователь 0m1.116s
пусть пользователь «i + = 1» 0m1.100s
пусть пользователь «i ++» 0m1.008s
пусть i = i + 1 пользователь 0m0.952s
пусть i + = 1 пользователь 0m1.040s
пусть i ++ пользователь 0m0.820s
declare -i i; i = i + 1 пользователь 0m0.528s
declare -i i; i + = 1 пользователь 0m0.492s
I = 0; i = $ (expr $ i + 1) пользователь 0m5.464s

Вывод:

Кажется, bash работает быстрее при выполнении i + = 1, когда $ i объявляется как целое число. Операторы let кажутся особенно медленными, а expr на сегодняшний день является самым медленным, поскольку он не является встроенным.

ответил Paul Tanzini 3 TueEurope/Moscow2013-12-03T20:38:03+04:00Europe/Moscow12bEurope/MoscowTue, 03 Dec 2013 20:38:03 +0400 2013, 20:38:03
14

Есть и это:

var = `expr $ var + 1`

Обратите внимание на пробелы, а также ` не

Хотя ответы Radu и комментарии являются исчерпывающими и очень полезными, они являются специфичными для bash. Я знаю, что вы специально задавали вопрос о bash, но я думал, что буду подключаться, поскольку нашел этот вопрос, когда искал сделать то же самое, используя sh в busybox под uCLinux. Этот переносной компьютер за пределами bash.

ответил tphelican 31 J000000Friday15 2015, 20:15:32
9

Если вы объявите $ var как целое число, то то, что вы пробовали в первый раз, действительно будет работать:

$ declare -i var = 5
$ echo $ var
5
$ var = $ var + 1
$ echo $ var
6

Ссылка: Типы переменных, руководство Bash для начинающих

ответил Radon Rosborough 23 AM00000020000003631 2016, 02:11:36
6

Во всех ответах отсутствует один метод - bc

$ VAR = 7
$ bc <"$ VAR + 2"
9
$ echo $ VAR
7
$ VAR = $ (bc <<"$ VAR + 1")
$ echo $ VAR
8

bc указан POSIX , поэтому он должен присутствовать во всех версиях Ubuntu и POSIX-совместимых систем. Переадресация << может быть изменена на echo "$ VAR" | bc для переносимости, но поскольку вопрос спрашивает о bash - это нормально, просто используйте <<lt;.

ответил Sergiy Kolodyazhnyy 7 MonEurope/Moscow2015-12-07T01:19:35+03:00Europe/Moscow12bEurope/MoscowMon, 07 Dec 2015 01:19:35 +0300 2015, 01:19:35
4

Код возврата 1 присутствует для всех вариантов по умолчанию (let, (()) и т. д.). Это часто вызывает проблемы, например, в сценариях, которые используют set -o errexit. Вот что я использую для предотвращения кода ошибки 1 из математических выражений, которые вычисляются до 0;

math () {(("$ @")) || правда; }

math a = 10, b = 10
math a ++, b + = 2
math c = a + b
math mod = c% 20
echo $ a $ b $ c $ mod
# 11 12 23 3
ответил Juve 23 FebruaryEurope/MoscowbThu, 23 Feb 2017 16:58:27 +0300000000pmThu, 23 Feb 2017 16:58:27 +030017 2017, 16:58:27

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132