回答:
let
bashビルトインを使用する別の方法:
$ let a="3 * (2 + 1)"
$ printf '%s\n' "$a"
9
注意
以下のようステファンChazelas @指摘して、bash
あなたが使用する必要がある((...))
上で算術演算を行うことexpr
やlet
読みやすさのために。
移植性のために$((...))
、@Bernhard answerのように使用します。
let
。これは、標準またはポータブルではなく(( a = 3 * (2 + 1) ))
(両方ともksh
ksh、bash、およびzshでのみ利用可能です)、読みにくく、引用も簡単です。a=$((3 * (2 + 1)))
ポータブルにするために使用します。
((a = 3 * (2 + 1) ))
、移植性のa=$((3 * (2 + 1)))
ためのもの)があるので使用すべきではないと言っているので、それはあなたまたはあなたの答えに対するメモではなく、選択された答えであることに対するものではありませんそして最高得点。
a=1 $[a+2]
またはを常に使用していa=1 b=2 $[a+b]
ます。その構文を避ける理由はありますか?
代わりに算術展開を使用できます。
echo "$(( 3 * ( 2 + 1 ) ))"
9
私の意見では、これはを使用するよりも少し見た目がいいですexpr
。
から man bash
算術展開 算術展開により、算術式の評価と結果の置換が可能になります。算術展開の形式は次のとおりです。
$((expression))
式は二重引用符内にあるかのように扱われますが、括弧内の二重引用符は特別に扱われません。式内のすべてのトークンは、パラメーターの展開、文字列の展開、コマンドの置換、および引用の削除を受けます。算術展開はネストできます。
評価は、算術評価で以下にリストされているルールに従って実行されます。式が無効な場合、bashは失敗を示すメッセージを出力し、置換は行われません。
expr
現代のシェルで算術演算に使用する理由はありません。
POSIXは$((...))
展開演算子を定義します。したがって、すべてのPOSIX準拠のシェル(sh
すべての最新のUnixライクなもの、ダッシュ、バッシュ、ヤッシュ、mksh、zsh、posh、ksh ...)でそれを使用できます。
a=$(( 3 * (2 + 1) ))
a=$((3*(2+1)))
ksh
またlet
、同じ種類の算術式が渡され、何かに展開されず、式が0に解決されるかどうかに基づいて終了ステータスを返す組み込み関数を導入しましたexpr
。
if let 'a = 3 * (2 + 1)'; then
echo "$a is non-zero"
fi
ただし、クォートによって扱いにくくなり、読みにくくなります(expr
もちろん同じ程度ではありません)のでksh
、((...))
代替形式も導入しました。
if (( a = 3 * (2 + 1) )) && (( 3 > 1 )); then
echo "$a is non-zero and 3 > 1"
fi
((a+=2))
これははるかに読みやすく、代わりに使用する必要があります。
let
そして、((...))
でのみ利用可能ですksh
、zsh
とbash
。$((...))
構文は、他のシェルへの移植が必要な場合、好まれるべきでexpr
のみプレPOSIXボーン状シェル(典型的にはBourneシェルまたはAlmquistシェルの初期バージョン)のために必要とされます。
非Bourneフロントには、算術演算子が組み込まれたいくつかのシェルがあります。
csh
/ tcsh
(実際には算術評価が組み込まれた最初のUnixシェル):
@ a = 3 * (2 + 1)
akanga
(に基づいてrc
)
a = $:'3 * (2 + 1)'
履歴メモとして、1989年にusenetに投稿されたAlmquistシェルのオリジナルバージョンにはexpr
組み込みがありましたが(実際にはにマージされましたtest
)、後で削除されました。
: $((a = a*2))
?
$((...))
zsh、ksh93、yashなどの浮動小数点をサポートするシェルが必要です。
expr
外部コマンドであり、特別なシェル構文ではありません。したがって、expr
シェルの特殊文字を表示する場合は、引用符で囲むことでシェルの解析から保護する必要があります。さらに、expr
各数値と演算子を個別のパラメーターとして渡す必要があります。副<文>この[前述の事実の]結果として、それ故に、従って、だから◆【同】consequently; therefore <文>このような方法で、このようにして、こんなふうに、上に述べたように◆【同】in this manner <文>そのような程度まで<文> AひいてはB◆【用法】A and thus B <文>例えば◆【同】for example; as an example:
expr 3 \* \( 2 + 1 \)
1970年代または1980年代のアンティークUnixシステムで作業しているのでない限り、を使用する理由はほとんどありませんexpr
。昔は、シェルには算術演算を実行する組み込みの方法がexpr
なく、代わりにユーティリティを呼び出す必要がありました。すべてのPOSIXシェルには、算術展開構文による算術が組み込まれています。
echo "$((3 * (2 + 1)))"
コンストラクト$((…))
は、算術式の結果(10進数で記述)に展開されます。Bashは、ほとんどのシェルと同様に、2 64を法とする整数演算のみをサポートします(32ビットマシン上の古いバージョンのbashおよびその他のシェルの場合は2 32を法とする)。
Bashには、割り当てを実行したり、式が0であるかどうかをテストしたいが結果を気にしたくない場合に便利な構文が追加されています。この構造はkshとzshにも存在しますが、プレーンなshには存在しません。
((x = 3 * (2+1)))
echo "$x"
if ((x > 3)); then …
整数演算に加えexpr
て、いくつかの文字列操作関数を提供します。これらもPOSIXシェルの機能に含まれていますが、1つを除きexpr STRING : REGEXP
ます:文字列が指定された正規表現に一致するかどうかをテストします。POSIXシェルは外部ツールなしでこれを行うことはできませんが、bashは[[ STRING =~ REGEXP ]]
(別の正規表現構文で — expr
古典的なツールであり、BREを使用し、bashはEREを使用します)使用できます。
20年前のシステムで実行されるスクリプトを保守しているのでなければ、それがexpr
存在することを知る必要はありません。シェル演算を使用します。
expr foo : '\(.\)'
テキスト抽出も行います。bash
のBASH_REMATCH
ようなものを達成します。また、POSIX [
が実行しない文字列比較も実行します(sort
そのための使用方法は想像できますが)。
引用符付きの括弧を使用します。
expr 3 '*' '(' 2 '+' 1 ')'
9
引用符は、bashが括弧をbash構文として解釈するのを防ぎます。
expr
コマンドラインのトークンをスペースで区切る必要があるということです。そう; たとえば、expr 3 "*" "(2" "+" "1)"
動作しません。(また、ところで、あなたはおそらく引用する必要はありません+
。)
while
と[[
、彼らは構文です。それらがキーワードである場合、コマンド引数ではそのように解釈されません。bashがそれらを解析せず、代わりに文字列リテラルを見るために引用符が必要です。