我尝试同时使用var=$var+1var=($var+1)递增数字变量,但未成功。该变量是一个数字,尽管bash似乎正在以字符串形式读取它。

Ubuntu 13.10上的Bash版本4.2.45(1)-发行版(x86_64-pc-linux-gnu)。

#1 楼

在bash中增加变量的方法有多种,但是您尝试的方法不正确。

您可以使用例如算术扩展:

var=$((var+1))
((var=var+1))
((var+=1))
((var++))


或者您可以使用let

let "var=var+1"
let "var+=1"
let "var++"


另请参见:http://tldp.org/LDP/abs/html/dblparens.html。

评论


或((++ var))或((var = var + 1))或((var + = 1))。

– gniourf_gniourf
13年12月3日在18:30

奇怪的是,var = 0; (((var ++)))在var = 0时返回错误代码; ((var ++)); (((var ++)))没有。知道为什么吗?

– phunehehe
2014年3月26日在9:36

@phunehehe查看帮助'((.。最后一行说:如果EXPRESSION的值为0,则返回1;否则,返回0。

– RaduRădeanu
2014年3月27日上午11:41

我怀疑零的评估为1就是为什么@gniourf_gniourf的提示包含((++ var))但不包含((var ++))的原因。

– DreadPirateShawn
2014年4月23日在16:17

使用不带引号的let var ++是否安全?

– wjandrea
17年6月14日在20:20



#2 楼

var=$((var + 1))


bash中的算法使用$((...))语法。

评论


比公认的答案好得多。在仅10%的空间中,您设法提供了足够的示例(一个足以说明问题-九个在您炫耀时就显得有些过分了),并且您向我们提供了足够的信息来知道((...) )是在bash中使用算术的关键。我没有意识到仅仅查看接受的答案-我认为关于操作顺序或导致接受的答案中所有括号的规则有一套怪异的规则。

–ArtOfWarfare
16年6月22日在13:56

#3 楼

各种以1递增的选项以及性能分析

感谢RaduRădeanu的回答,它提供了以下以bash递增变量的方法:

var=$((var+1))
((var=var+1))
((var+=1))
((var++))
let "var=var+1"
let "var+=1" 
let "var++"


还有其他方法。例如,查看有关此问题的其他答案。

let var++
var=$((var++))
((++var))
{
    declare -i var
    var=var+1
    var+=1
}
{
    i=0
    i=$(expr $i + 1)
}


有这么多的选择会导致以下两个问题:


它们之间是否有性能差异?
如果哪种效果最好?

性能增量测试代码:

#!/bin/bash

# To focus exclusively on the performance of each type of increment
# statement, we should exclude bash performing while loops from the
# performance measure. So, let's time individual scripts that
# increment $i in their own unique way.

# Declare i as an integer for tests 12 and 13.
echo > t12 'declare -i i; i=i+1'
echo > t13 'declare -i i; i+=1'
# Set i for test 14.
echo > t14 'i=0; i=$(expr $i + 1)'

x=100000
while ((x--)); do
    echo >> t0 'i=$((i+1))'
    echo >> t1 'i=$((i++))'
    echo >> t2 '((i=i+1))'
    echo >> t3 '((i+=1))'
    echo >> t4 '((i++))'
    echo >> t5 '((++i))'
    echo >> t6 'let "i=i+1"'
    echo >> t7 'let "i+=1"'
    echo >> t8 'let "i++"'
    echo >> t9 'let i=i+1'
    echo >> t10 'let i+=1'
    echo >> t11 'let i++'
    echo >> t12 'i=i+1'
    echo >> t13 'i+=1'
    echo >> t14 'i=$(expr $i + 1)'
done

for script in t0 t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t11 t12 t13 t14; do
    line1="$(head -1 "$script")"
    printf "%-24s" "$line1"
    { time bash "$script"; } |& grep user
    # Since stderr is being piped to grep above, this will confirm
    # there are no errors from running the command:
    eval "$line1"
    rm "$script"
done


结果:

i=$((i+1))              user    0m0.992s
i=$((i++))              user    0m0.964s
((i=i+1))               user    0m0.760s
((i+=1))                user    0m0.700s
((i++))                 user    0m0.644s
((++i))                 user    0m0.556s
let "i=i+1"             user    0m1.116s
let "i+=1"              user    0m1.100s
let "i++"               user    0m1.008s
let i=i+1               user    0m0.952s
let i+=1                user    0m1.040s
let i++                 user    0m0.820s
declare -i i; i=i+1     user    0m0.528s
declare -i i; i+=1      user    0m0.492s
i=0; i=$(expr $i + 1)   user    0m5.464s


结论:

当将i+=1声明为整数时,bash似乎最快地执行了$ilet语句似乎特别慢,而expr到目前为止是最慢的,因为它不是bash内置的。

评论


显然,速度与命令长度相关。我不知道这些命令是否调用相同的功能。

–马修·洛克(MatthewRock)
17年1月5日在15:40

不是OP问的。

–raygozag
19/12/15在18:12

@raygozag操作员询问如何增加。我的答案首先列出了许多方法。那怎么不直接回答op问题呢?然后,它为每种方法提供时间信息。就是说,这些只是补充信息,可以帮助操作员选择他想使用的方法。

–基思·雷诺兹
19/12/15在18:33

已经回答了,OP并没有要求绩效评估,无论您希望获得多大帮助,他们都没有要求。

–raygozag
19/12/16在14:09

我发现在Bash 3.2.57上,使用声明-i x,然后在循环中执行x + = 1(执行其他操作),x的增量不超过一次。 let和(())方法工作正常。

–乔恩·斯宾塞
1月9日21:59

#4 楼

还有一个:

var=`expr $var + 1`


请注意空格,并且`不是'

Radu的答案和评论都是详尽无遗且非常有帮助,它们是针对bash的。我知道您确实曾问过有关bash的问题,但是我想加入,因为当我想在uCLinux下的busybox中使用sh进行相同的操作时发现了这个问题。超越bash的便携式产品。

评论


您也可以使用i = $((i + 1))

– wjandrea
17年6月14日在22:58

如果此外壳上有进程替换$(...),我建议改用它。

–拉登·罗斯伯勒(Radon Rosborough)
17年8月24日在18:54

#5 楼

如果您将$var声明为整数,那么您第一次尝试的方法实际上将起作用:

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


参考:变量类型,Bash初学者指南

#6 楼

所有答案中都缺少一种方法-bc由POSIX标准指定,因此应该在所有版本的Ubuntu和POSIX兼容系统中都存在。为了便于携带,可以将bc重定向更改为<<<,但是由于该问题询问了echo "$VAR" | bc-可以只使用bash

#7 楼

所有默认变体(1let等)都存在返回码(())的问题。这通常会造成麻烦,例如,在使用set -o errexit的脚本中。这是我用来防止错误代码1的数学表达式得出0的原因;

math() { (( "$@" )) || true; }

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


#8 楼

这必须是完成这样一个简单任务的最糟糕的方法,但是我想只是出于乐趣的目的对其进行记录(与代码高尔夫完全相反)。

$ var=0
$ echo $var
0
$ var="$(python -c 'print('$var'+1)')"
$ echo $var
1




$ var="$(printf '%s\n' $var'+1' | bc)"
$ echo $var
1


在这里认真使用其他更好的选择之一。