Bashで2つの変数を減算する


220

2つのディレクトリ間のファイル数を減算する次のスクリプトがありますが、COUNT=式が機能しません。正しい構文は何ですか?

#!/usr/bin/env bash

FIRSTV=`ls -1 | wc -l`
cd ..
SECONDV=`ls -1 | wc -l`
COUNT=expr $FIRSTV-$SECONDV  ## -> gives 'command not found' error
echo $COUNT

回答:


224

あなたはマイナス記号の周りに少し余分な空白とバッククォートが必要です:

COUNT=`expr $FIRSTV - $SECONDV`

終了ステータスに注意してください。

EXPRESSIONがnullでも0でもない場合、終了ステータスは0です。EXPRESSIONがnullまたは0である場合1です

コマンドがゼロ以外のステータスで終了するとすぐに終了するset -eと組み合わせてbashスクリプトで式を使用する場合は、このことを覚えておいてください。


2
この回答はposix shシェルでも機能します。移植性のために、この回答を使用することをお勧めします。
2016年

Shellcheckによると、exprは古くて使いにくいため、コードメルであることに注意してください:github.com/koalaman/shellcheck/wiki/SC2003
John Hamelink

369

外部プログラムを使用する代わりに、次のBash構文を試してくださいexpr

count=$((FIRSTV-SECONDV))

ところで、正しい構文exprは次のとおりです。

count=$(expr $FIRSTV - $SECONDV)

ただし、使用exprすると、上で提供した内部のBash構文よりも遅くなることに注意してください。


4
この形式は、expr外部プログラムを使用するよりもはるかに高速です。
nsg 2013

これはバッククォートなしで機能しますが、なぜでしょうか?answe.rの+1
Amal Murali

2
ありがとう。バックティックは古いシェル構文です。BASHは$(command)、コマンド置換の新しい構文をサポートしています。また、BASHは算術演算をサポート$(( ... ))しているため、外部ユーティリティを使用しない方がよいexpr
anubhava

1
私はあなたが「$」なしで変数を参照することができたことを決して新しくありません、非常に興味深いです。これは、Ubuntu 12,14でのみ機能します。
MadHatter

1
@ AlikElzin-kilaka:bash $(( ... ))では、算術式の評価に使用されます。
anubhava 2017

30

以下を使用できます。

((count = FIRSTV - SECONDV))

次のトランスクリプトに従って、別のプロセスを呼び出さないようにします。

pax:~$ FIRSTV=7
pax:~$ SECONDV=2
pax:~$ ((count = FIRSTV - SECONDV))
pax:~$ echo $count
5

12

空白は重要であり、exprそのオペランドと演算子を別々の引数として期待します。また、出力をキャプチャする必要があります。このような:

COUNT=$(expr $FIRSTV - $SECONDV)

しかし、組み込みの算術展開を使用する方が一般的です。

COUNT=$((FIRSTV - SECONDV))

12

これは私がいつもバッシュで数学をする方法です:

count=$(echo "$FIRSTV - $SECONDV"|bc)
echo $count

5
これは、浮動小数点数を扱う場合にのみ必要です。
グレン・ジャックマン、2011

2
私はそれを理解していますが、|bc1回か2回見逃すのではなく、タイプコマンドを使用してこれらのケースをキャッチする習慣をつけたいと思います。彼らが言うように、異なる人々のための異なるストローク。
Pureferret、2011

5

単純な整数演算の場合は、組み込みのletコマンドを使用することもできます。

 ONE=1
 TWO=2
 let "THREE = $ONE + $TWO"
 echo $THREE
    3

の詳細についてはletこちらをご覧ください


@ another.anon.cowardあなたのリンクは私の+1よりも優れています。(...および盗むリンク)
Shawn Chin

これを機能させるのに多くの問題がありました。最後にこれはlet "sanity_check_duration=sanity_check_duration_end_time_delay_sec - sanity_check_duration_start_time_delay_sec"
うまくいき

2

提案された3つの方法の代わりに、let次のように変数に対して算術演算を実行することができます。

let COUNT=$FIRSTV-$SECONDV

または

let COUNT=FIRSTV-SECONDV


0

Pythonを使用:

#!/bin/bash
# home/victoria/test.sh

START=$(date +"%s")                                     ## seconds since Epoch
for i in $(seq 1 10)
do
  sleep 1.5
  END=$(date +"%s")                                     ## integer
  TIME=$((END - START))                                 ## integer
  AVG_TIME=$(python -c "print(float($TIME/$i))")        ## int to float
  printf 'i: %i | elapsed time: %0.1f sec | avg. time: %0.3f\n' $i $TIME $AVG_TIME
  ((i++))                                               ## increment $i
done

出力

$ ./test.sh 
i: 1 | elapsed time: 1.0 sec | avg. time: 1.000
i: 2 | elapsed time: 3.0 sec | avg. time: 1.500
i: 3 | elapsed time: 5.0 sec | avg. time: 1.667
i: 4 | elapsed time: 6.0 sec | avg. time: 1.500
i: 5 | elapsed time: 8.0 sec | avg. time: 1.600
i: 6 | elapsed time: 9.0 sec | avg. time: 1.500
i: 7 | elapsed time: 11.0 sec | avg. time: 1.571
i: 8 | elapsed time: 12.0 sec | avg. time: 1.500
i: 9 | elapsed time: 14.0 sec | avg. time: 1.556
i: 10 | elapsed time: 15.0 sec | avg. time: 1.500
$
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.