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

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回答

コメント

  • +1さらに読みやすくなります! Linuxユーザーの仲間に役立つと思って質問と回答を投稿しましたが、今では他の回答から多くのメリットを得ています:-)
  • そこに' letを使用する理由はありません。 'は(( a = 3 * (2 + 1) ))(どちらもkshからのもの)よりも標準的または移植性がありません。 ksh、bash、zshでのみ利用可能です)、'読みにくく、引用しにくいです。 a=$((3 * (2 + 1)))を使用して移植性を高めます。
  • '言っていない'間違っています、私は'より良い代替手段があるので使用すべきではないと言っています(読みやすさのための((a = 3 * (2 + 1) ))、1つ移植性のためにa=$((3 * (2 + 1))))、それで'はあなたやあなたの答えに対するメモではなく、選択された答えと最高得点者に対するメモです。
  • @St é faneChazelas:回答を更新しました!
  • 私はいつもa=1 $[a+2]またはa=1 b=2 $[a+b]。その構文を避ける理由はありますか?

回答

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

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))) 

kshletビルトインを導入しました。同じ種類の算術式が渡され、何かに展開されませんが、式が解決されるかどうかに基づいて終了ステータスを返します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および((...))は、kshzshおよび

$((...))構文は、他のシェルへの移植性が必要な場合に推奨されます。exprは、POSIX以前のBourneのようなシェル(通常はBourneシェルまたはAlmquistシェルの初期バージョン)。

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

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

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

    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などの$((...))の浮動小数点をサポートするシェルが必要です。

回答

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

expr 3 \* \( 2 + 1 \) 

1970年代または1980年代の旧式のUNIXシステムで作業している場合を除き、。昔は、シェルには算術演算を実行する組み込みの方法がなく、代わりに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は、いくつかの文字列操作関数を提供します。これらも、1つを除いて、POSIXシェルの機能に含まれています。expr STRING : REGEXPは、文字列が指定されたregexpと一致するかどうかをテストします。POSIXシェルは、これがないと実行できません。外部ツールですが、bashは[[ STRING =~ REGEXP ]]異なるregexp構文exprは古典的なツールであり、BREを使用し、bashはEREを使用します。

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

コメント

  • expr foo : '\(.\)'もテキスト抽出を行います。 bash 'のBASH_REMATCHも同様のことを実現します。また、POSIX [では実行されない文字列比較も実行します(ただし、sortを使用する方法を想像することはできます)。
  • 構文プレースホルダーとしてのアンダースコア—あなたはSchemer、@ Giles? :]
  • @RubyTuesdayDONOここではアンダースコアを使用しませんでした'。 U + 2026 HORIZONTAL ELLIPSISを読み間違えていますか?その場合は、より大きなフォントを使用してみてください。
  • @Giles —はい、フォントサイズが原因で、アンダースコアのように見えます。私にとって、"スキーマ"は補足であり、'は省略記号とは異なります。対アンダースコアはとにかく意味を変えます…それについて卑劣になる必要はありません:/

答え

括弧を使用して引用符:

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

引用符は、bashが括弧をbash構文として解釈するのを防ぎます。

コメント

  • Nicolasが説明しているが説明していないのは、exprコマンドラインのトークンはスペースで区切る必要があるということです。そう;たとえば、expr 3 "*" "(2" "+" "1)" は機能しません 。 (また、ところで、おそらく+を引用する必要はありません。)
  • 括弧は' while[[、それらは'構文です。 それらがキーワードである場合、コマンド引数では'そのように解釈されません。 bashが'を解析せず、代わりに文字列リテラルを表示するように、引用符が必要です。

回答

bcがある場合..

echo "3 * (2 + 1)"|bc 9 

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です