expr
は括弧が好きではないようです(使用数学で明示的な演算子の優先順位に):
expr 3 * (2 + 1) bash: syntax error near unexpected token `("
bashで演算子の優先順位を表現する方法
回答
let
bash組み込みを使用する別の方法:
$ let a="3 * (2 + 1)" $ printf "%s\n" "$a" 9
注
@StéphaneChazelasが指摘したように、bash
では、((...))
を使用してexpr
または読みやすさのためにlet
。
移植性のために、$((…))を使用します。 > @Bernhard回答。
コメント
回答
代わりに算術展開を使用できます。
echo "$(( 3 * ( 2 + 1 ) ))" 9
私の個人的な意見では、これはexpr
を使用するよりも少し見栄えがします。
man bash
算術拡張算術展開により、算術式の評価と結果の置換が可能になります。算術展開の形式は次のとおりです。
$((expression))
式は二重引用符で囲まれているように扱われますが、括弧内の二重引用符は特別に扱われません。式内のすべてのトークンは、パラメーター展開、文字列展開、コマンド置換、および引用符の削除を受けます。算術展開はネストできます。
評価は、以下の算術評価のルールに従って実行されます。式が無効な場合、bashは失敗を示すメッセージを出力し、置換は発生しません。
コメント
- 読みやすさは別として、'算術演算を行うために追加のプロセスをフォークする必要もありません。 'はシェル自体によって処理されます。
- POSIXシェルでは、'は単語の対象となることに注意してください。分割するので、'リストコンテキストで引用するのが良い習慣です。
- bashシェルでこれを試すと、変数名が無効です。"
回答
最新のシェルの演算にexpr
を使用する理由はありません。
POSIXは$((...))
を定義しています。拡張演算子。したがって、POSIX準拠のすべてのシェル(ダッシュ、bash、yash、mksh、zsh、posh、kshなどの最新のUnixのsh
で使用できます。 )。
a=$(( 3 * (2 + 1) )) a=$((3*(2+1)))
ksh
もlet
ビルトインを導入しました。同じ種類の算術式が渡され、何かに展開されませんが、式が解決されるかどうかに基づいて終了ステータスを返しますexpr
のように、esを0にするかどうか:
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
および
。$((...))
構文は、他のシェルへの移植性が必要な場合に推奨されます。expr
は、POSIX以前のBourneのようなシェル(通常はBourneシェルまたはAlmquistシェルの初期バージョン)。
Bourne以外のフロントには、算術演算子が組み込まれたシェルがいくつかあります。
-
csh
/tcsh
(実際には、算術評価が組み込まれた最初のUnixシェル):@ a = 3 * (2 + 1)
-
akanga
(rc
に基づく)a = $:"3 * (2 + 1)"
-
履歴メモとして、1989年にusenetに投稿されたAlmquistシェルの元のバージョンには
expr
ビルトイン(実際にはtest
とマージされています)が、後で削除されました。
コメント
- St é phaneさんから毎日新しいことを学びます。 POSIXシェルの知識に感謝します!
-
: $((a = a*2))
はどうですか? - 浮動小数点がある場合はどうなりますか?私の式はa = $((-14 + 0.2 *(1 + 2 + 3)))です。エラートークンは" .2 *(1 + 2 + 3)"
- @Blaiseです。 ' dには、zsh、ksh93、yashなどの
$((...))
の浮動小数点をサポートするシェルが必要です。
let
を使用する理由はありません。 'は(( a = 3 * (2 + 1) ))
(どちらもksh
からのもの)よりも標準的または移植性がありません。 ksh、bash、zshでのみ利用可能です)、'読みにくく、引用しにくいです。a=$((3 * (2 + 1)))
を使用して移植性を高めます。((a = 3 * (2 + 1) ))
、1つ移植性のためにa=$((3 * (2 + 1)))
)、それで'はあなたやあなたの答えに対するメモではなく、選択された答えと最高得点者に対するメモです。a=1 $[a+2]
またはa=1 b=2 $[a+b]
。その構文を避ける理由はありますか?