2つの文字列があります
str1="( 1 + 2 + 3 + 4 + 5 ) / 3 + 5"
そして
str2="( 1 + 2 + 3 + 4 + 5 ) / 3 + 5 * 2"
注文する
result=` expr $str1`
中に正しい値を返します。
result=` expr $str2`
返品expr: syntax error
答え1
以下は間違った結果を生成します。
str2="( 1 + 2 + 3 + 4 + 5 ) / 3 + 5 * 2"
expr $str2
問題は、シェルが*
ワイルドカードファイルglobを考え、それを現在のディレクトリのファイルリストに置き換えるということです。あなたが望むものではありませんか?
expr
古代です。より近代的な解決策は、シェル$((...))
形式の算術を使用することです。
$ str2="( 1 + 2 + 3 + 4 + 5 ) / 3 + 5 * 2"
$ echo "$((str2))"
15
シェルは整数演算のみを実行します。浮動小数点の正確な結果が本当に必要な場合(ここでも同様)、以下を使用してくださいbc
。
$ echo "$str2" | bc -l
15.00000000000000000000
$str2
シェルのたわみを防ぐには、二重引用符を使用してください。
答え2
二重引用符の外側で変数を展開すると(に示すように)、expr $str2
次のことが発生します。
- 変数の値を取得します。結果は文字列です。
- 値をスペースで区切られたチャンクに分割します。結果は文字列のリストです。
- リストの各要素をワイルドカードパターンとして解釈します。ワイルドカード。ファイルと一致すると、その要素を一致するリストに置き換えます。一致するファイルがない場合、要素は保持されます。
たとえば、値に単語を含む変数は、*
現在のディレクトリにあるファイル名のリストに置き換えられます。
通常、変数置換とコマンド置換は常に二重引用符("$stuff"
、)で囲まれています"`stuff`"
。バラよりスペースやその他の特殊文字が原因でシェルスクリプトが停止するのはなぜですか?引用符が必要な理由を知って理解している場合にのみ、引用符を省略してください。
expr
この場合、演算子とオペランドは別々のパラメータにある必要があるため、手順2(分割)を実行する必要があります。ただし、ステップ3(各単語をファイル名のワイルドカードパターンとして扱う)は行わないでください。ワイルドカードをオフにしてこれを行うことができます。
result=`set -f; expr $str2`
ksh または bash では、文字列の代わりに配列を使用します。しかし、そのシェルではexpr
。
スクリプトを古代のBourneシェルに移植する必要がない限り、それを使用する必要はありませんexpr
。算術式は標準 POSIX 関数です。
result=$(($str2))
1区切り文字はIFS
変数で設定できます。