bashで変数をインクリメントする方法は?


609

両方var=$var+1を使用して、var=($var+1)成功せずに数値変数をインクリメントしようとしました。変数は数値ですが、bashは文字列として読み取っているようです。

Ubuntu 13.10上のBashバージョン4.2.45(1)-release(x86_64-pc-linux-gnu)

回答:


947

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も参照してください。


31
または((++var))または((var=var+1))または((var+=1))
gniourf_gniourf

6
奇妙なことにvar=0; ((var++))、エラーコードを返しますが、返しvar=0; ((var++)); ((var++))ません。理由は何ですか?
プネヘヘ14年

15
@phuneheheを見てくださいhelp '(('。最後の行は言う:Returns 1 if EXPRESSION evaluates to 0; returns 0 otherwise.
ラドゥRădeanu

2
1@gniourf_gniourfのtipには含まれて((++var))いますが、含まれていないのは、ゼロの評価が疑われるため((var++))です。
DreadPirateShawn

4
それを使用しても安全であるlet var++、引用符なしで、?
-wjandrea

160
var=$((var + 1))

bashの算術では$((...))構文が使用されます。


9
受け入れられた答えよりもはるかに良い。ちょうど10%くらいのスペースでは、あなたは十分な例を(1がたくさんある- 9は、あなただけ披露しているポイントにやり過ぎである)を提供するために管理し、あなたはそれを知るために十分な情報を提供してくれました((...))算術を使用するための鍵ですバッシュ。受け入れられた答えを見ただけでは気づきませんでした-操作の順序や受け入れられた答えのすべての括弧につながる何かに関する奇妙なルールがあると思いました。
ArtOfWarfare

82

さまざまなオプションのパフォーマンス分析

bashで変数をインクリメントする次の方法を提供するRaduRădeanuの回答に感謝します。

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)
}

非常に多くのオプションがあると、次の2つの質問につながります。

  1. それらの間にパフォーマンスの違いはありますか?
  2. もしそうなら、どれが最高のパフォーマンスを発揮しますか?

増分パフォーマンステストコード:

#!/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は実行が最も速いよう$iです。letステートメントは特に遅いように見えexprますが、組み込みではないため、最も遅いです。


速度は明らかにコマンドの長さと相関しています。コマンドが同じ関数を呼び出すかどうか疑問に思います。
マシューロック

18

これもあります:

var=`expr $var + 1`

スペースに注意してください。また、「ではない

Raduの回答とコメントは網羅的で非常に有用ですが、bash固有のものです。bashについて具体的に質問したことは知っていますが、uCLinuxのbusyboxでshを使用して同じことをしようとしていたときにこの質問を見つけたので、パイプを入れようと思いました。bashを超えたこのポータブル


1
また使用することができますi=$((i+1))
-wjandrea

$(...)このシェルでプロセス置換が使用可能な場合は、代わりに使用することをお勧めします。
ラドンロズバラ


7

すべての答えに欠けている1つの方法があります- bc

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

bcPOSIX標準で指定されいるため、UbuntuおよびPOSIX準拠システムのすべてのバージョンに存在する必要があります。<<<リダイレクトはに変更することができるecho "$VAR" | bc質問を約尋ねるので、移植性のために、しかしbash-それだけで使用するためにOKです<<<


6

リターンコードの1問題は、すべてのデフォルトバリアント(のために存在しているlet(())など)。これにより、たとえばを使用するスクリプトで問題が発生することがよくあります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

0

これは、このような単純なタスクを達成するための最悪の方法でなければなりませんが、楽しみのためにそれを文書化したかっただけです(コードゴルフの完全な反対)。

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

または

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

ここでは、他のはるかに優れた選択肢の1つを真剣に使用します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.