bash - 変数の合計

bash - 変数の合計

数字をスペースで区切る変数のセットがあります。ここで、最初の数字はスペースにつながる可能性があります。たとえば、次のようになります。

VAR=" 2 1  34 3    2 "

これらの数字をすべて追加する必要があります。最も簡単な方法は、数字の間のすべてのスペースを+bcのパイプに置き換えることです。

forループ、貼り付け、bcを使用して実行できますが、より簡単な方法を知っている人はいますか?VARbash組み込み文字列置換機能を使用してbashで直接計算を実行できますか?

$ for i in $VAR;do echo $i;done|paste -sd+|bc
42

更新:すべての提案のおかげで、最終的に配列を使用するかなり短い方法が見つかりました。

$ VAR=" 2 1  34 3    2 "
$ arr=( $VAR );echo "$((${arr[@]/%/+}0))"
42
$ VAR="$VAR -14"
$ arr=( $VAR );echo "$((${arr[@]/%/+}0))"
28
$

ベストアンサー1

ソース文字列には、繰り返されるスペースと先行/末尾のスペースが含まれています。

単純な空間変換は+失敗します。

$ value='      2 1  34 3    2    '
$ echo "${value// /+}"
++++++2+1++34+3++++2++++

繰り返される空白すべて折りたたみそして先行/末尾の空白を削除するには、引用符を持たない変数のみをエコー(またはprintf)します(IFSがデフォルトと仮定)。

value=$(echo $value)
echo "${value// /+}"
2+1+34+3+2

これはbcに提供できます。

$ echo "${value// /+}" | bc
42

必要に応じて1行にすべての内容:

value=$(echo $value); echo "${value// /+}" | bc

あるいは、sedフィルタとして使用することもできます(追加の変数はありませんが遅い)。

echo $value | sed 's/ /+/g' | bc

以前の試みで<<<問題が発生しました。

$ ~/bin/b44sh -c 'value="      2 1  34 3    2    ";sed "s/ /+/g" <<<$value'
++++++2+1++34+3++++2++++

バージョン4.4からbashで。以前のバージョンでは、次のように動作しました。

~/bin/b43sh -c 'value="      2 1  34 3    2    ";sed "s/ /+/g" <<<$value'
2+1+34+3+2

bash(およびsed)のすべてのバージョンで次のことができます(かなり強力なバージョンですが、外部ユーティリティを呼び出す - sed)。

sed "s/ \+/+/g" <<<"0 $value 0"     | tee /dev/tty     | bc
0+2+1+34+3+2+0
42

純粋なシェルソリューション(交換${//}部分としてbash、ksh、またはzshが必要)は次のとおりです。

value=$(echo $value); bc <<<"${value// /+}

もう一つあります。強い(ホームラン™)と持ち運べるバージョン:

  • IFSへの変更が現在のシェルに影響を与えないようにします。サブシェルを使用してください(…)
  • IFSが空白の値を分割していることを確認してください(IFS = "")。
  • 引用符なしで文字列が拡張されないことを確認します*(set -f).
  • +部品が(IFS = +)で接続されていることを確認してください。

( IFS=" "; set -f; set -- $value; IFS=+; echo "$*" | bc; )

機能バージョン1 -
シェルがそれを許可しない場合は、localより遅いサブシェルを使用してください。フォーム
2 - 一部(POSIXでは正しい)は、引用符なしで使用することについて文句を言うことができます$*

sum(){ local IFS=" "; set -f; set -- $*; IFS=+; echo "$*" | bc; }

さまざまな方法でパラメータを追加します。

$ value="      2 1  34 3    2    "
$ sum "$value"
42
$ sum $value    # beware of glob chars *, ? and [  and of odd IFS=123 settings
42
$ sum "      2 1  34 3    2    "
42
$ sum "      2"    "1  "    "34 3"    "    2    "
42
$ var=23
$ sum "      2"    "1  "    "34 3"    "    2    "   "$var"
65

おすすめ記事