web-dev-qa-db-ja.com

バッシュの乗算と加算

for k in {0..49};
do
a=$(($((2*$k))+1));
echo $a;
done

こんにちは、3行目の簡略化された式が必要です。コマンド置換を使用しない式の可能性があります。

20
AVS

算術展開を使用する:

for (( k = 0; k < 50; ++k )); do
  a=$(( 2*k + 1 ))
  echo "$a"
done

時代遅れのexprユーティリティを使用する:

for (( k = 0; k < 50; ++k )); do
  a=$( expr 2 '*' "$k" + 1 )
  echo "$a"
done

bc -lの使用(この場合、数学関数は使用されないため、-lは実際には必要ありません):

for (( k = 0; k < 50; ++k )); do
  a=$( bc -l <<<"2*$k + 1" )
  echo "$a"
done

bc -lをコプロセスとして使用する(バックグラウンドで一種の計算サービスのように動作します¹):

coproc bc -l

for (( k = 0; k < 50; ++k )); do
  printf "2*%d + 1\n" "$k" >&${COPROC[1]}
  read -u "${COPROC[0]}" a
  echo "$a"
done

kill "$COPROC_PID"

最後のものはksh93で(おそらく)よりクリーンに見えます:

bc -l |&
bc_pid="$!"

for (( k = 0; k < 50; ++k )); do
  print -p "2*$k + 1"
  read -p a
  print "$a"
done

kill "$bc_pid"

¹これにより、ループ内で大量の入力を処理する必要があった問題がかつて解決しました。処理にはいくつかの浮動小数点計算が必要でしたが、ループでのbcの数回の生成は非常に遅いことが判明しました。はい、他の方法で解決することもできましたが、退屈でした...

32
Kusalananda

簡略化できます:

a=$(($((2*$k))+1));

に:

a=$((2*k+1))
14
Jeff Schaller

letコマンドを使用して、計算を強制できます。

let a="2*k+1"

この構造には$kは必要ないことに注意してください。単純なkで十分です。

5
Stephen Harris

おそらく必要な算術展開はこれです:

_a=$(( 1+2*k ))
_

実際、変数を使用する必要はありません。

_for k in {0..49}; do
    echo "$(( 1 + 2*k ))"
done
_

または、カウント変数をfor ((…))ループに移動できます。

_for (( k=0;k<50;k++ )); do
    a=$(( 1+2*k ))
    printf '%s\n' "$a"
done
_

for((…))ループ

そして、その場合、算術展開はforループ内に移動することもできます。

_for (( k=0 ; a=1+2*k , k<50 ;  k++)); do
    printf '%s\n' "$a"
done
_

または、配列内のすべての値を取得するには:

_for (( k=0 ; a[k]=1+2*k , k<49 ;  k++ )); do :; done
printf '%s\n' "${a[@]}"
_

式なし

しかし、おそらく算術展開を回避する最も短い方法は、変数を2回インクリメントすることです。

_for (( k=0,a=1 ; k<50 ;  k++,a++,a++ )); do
    printf '%s\n' "$a"
done
_

または、さらに簡単に、seqを使用します。

_seq 1 2 100
_
2
user79743