web-dev-qa-db-ja.com

expr演算の括弧:3 *(2 + 1)

exprは括弧が好きではないようです(数学では演算子の優先順位を明示するために使用されます)。

expr 3 * (2 + 1)
bash: syntax error near unexpected token `('

演算子の優先順位をbashで表現する方法は?

64
Nicolas Raoul

組み込みのlet bashを使用する別の方法:

_$ let a="3 * (2 + 1)"
$ printf '%s\n' "$a"
9
_

@StéphaneChazelasが指摘 のように、bashでは、読みやすくするために_((...))_を使用してexprまたはletを計算する必要があります。

移植性のために、_ @ Bernhard answer のように$((...))を使用します。

41
cuonglm

代わりに算術展開を使用できます。

echo "$(( 3 * ( 2 + 1 ) ))"
9

私の個人的な意見では、これはexprを使用するよりも少し良く見えます。

man bashから

算術展開算術展開では、算術式の評価と結果の置換が可能です。算術展開の形式は次のとおりです。

         $((expression))

式は二重引用符内にあるかのように扱われますが、括弧内の二重引用符は特別に扱われません。式内のすべてのトークンは、パラメーター展開、文字列展開、コマンド置換、引用符の削除を受けます。算術展開は入れ子にすることができます。

評価は、以下の算術評価の下にリストされているルールに従って実行されます。式が無効な場合、bashは失敗を示すメッセージを出力し、置換は行われません。

79
Bernhard

最近のシェルで算術演算にexprを使用する理由はありません。

POSIXは$((...))拡張演算子を定義しています。そのため、すべてのPOSIX準拠シェル(最新のUnixライク、ダッシュ、bash、yash、mksh、zsh、posh、kshなどのsh)でそれを使用できます。

_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および_((...))_は、kshzsh、およびbashでのみ使用できます。他のシェルへの移植性が必要な場合は、$((...))構文をお勧めします。exprは、POSIX以前のBourneのようなシェル(通常はBourneシェルまたは初期バージョンのAlmquistシェル)でのみ必要です。

Bourne以外のフロントでは、算術演算子が組み込まれたシェルがいくつかあります。

  • csh/tcsh(実際には、算術評価が組み込まれた最初のUnixシェル):

    _@ a = 3 * (2 + 1)
    _
  • akangarcに基づく)

    _a = $:'3 * (2 + 1)'
    _
  • 歴史ノートとして、1989年にusenetに投稿されたAlmquistシェルのオリジナルバージョンには、exprビルトイン(実際にはtestとマージされました)がありましたが、後で削除されました。

40

exprは外部コマンドであり、特別なシェル構文ではありません。したがって、exprでシェルの特殊文字を表示するには、引用符で囲んでシェルの解析から保護する必要があります。さらに、exprでは、各数値と演算子を個別のパラメーターとして渡す必要があります。したがって:

_expr 3 \* \( 2 + 1 \)
_

1970年代または1980年代のアンティークUNIXシステムで作業しているのでない限り、exprを使用する理由はほとんどありません。昔は、シェルには算術を実行する組み込みの方法がなく、代わりにexprユーティリティを呼び出す必要がありました。すべてのPOSIXシェルには、 算術展開 構文による算術が組み込まれています。

_echo "$((3 * (2 + 1)))"
_

構文$((…))は、算術式の結果(10進数で記述)に展開されます。ほとんどのシェルと同様に、bashは2を法とする整数演算のみをサポートします。64 (または2を法とする32 古いバージョンのbashおよび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はクラシックツールであり、bashはEREを使用します)。

20年前のシステムで実行されるスクリプトを保守しているのでない限り、exprが存在していたことを知る必要はありません。シェル演算を使用します。

括弧と引用符を使用します。

expr 3 '*' '(' 2 '+' 1 ')'
9

引用符は、bashが括弧をbash構文として解釈しないようにします。

13
Nicolas Raoul

あなたがBCを持っているなら...

echo '3 * (2 + 1)'|bc 
9                                                                    
1
rob