質問しました

質問しました

このスクリプトは次のとおりです。

a=2
[[ "$a" -eq 2 ]] && echo yes1
[[  $a  -eq 2 ]] && echo yes2
[[   a  -eq 2 ]] && echo yes3
[[  "a" -eq 2 ]] && echo yes4

該当しない(そして[[がない他のものもあります)。
最後の2回の「はいテスト」に失敗しました。(BusyBoxグレー)。私が期待したように。

しかし、非常に予想外のことです。
これは、算術「-eq」(およびその他の算術)を使用する場合に発生します。
4つすべてを印刷するのはそして

質問しました

これは()のようなラベルに適用される「算術拡張」の自然な副作用ですかa
(何もないのに歩き続けよう?)

()を引用するときは、aまだ変数に拡張する必要がありますか"a"

まだ調査していないところにこの内容が記録されていますか?

それとも単純な(非常に古い)間違いですか?

編集する

実際に考えるには、以下を確認してください。

a=2; b=2

[[ "$a" -eq "$b"                 ]] && echo yes1
[[  $a  -eq "$b"                 ]] && echo yes2
[[   a  -eq "$b"                 ]] && echo yes3
[[  "a" -eq "$b"                 ]] && echo yes4
[[ "$a" -eq "$b" && "$a" == "$b" ]] && echo new1
[[  $a  -eq "$b" &&  $a  == "$b" ]] && echo new2
[[   a  -eq "$b" &&   a  == "$b" ]] && echo new3
[[  "a" -eq "$b" &&  "a" == "$b" ]] && echo new4

new1とnew2を除くすべての操作。 var a は new3 と 4 では拡張されません。

これは、計算中にシェルがモード(算術文字列)を切り替えることを意味します。

これは私には明らかではないようです。少なくとも私の考えではそうではありません。

Ashは他の方法でこれを行います。また、エラーを報告します。

結論として:

私は正解を知らない。しかし、私はこれが(開発者にとって)テストが機能するはずのよく知られている方法だと思います(まったく同じ方法で実行される多数のシェルを見ると)。事実を知って適応しなければなりません。

-eq数字の場合に適用できる唯一の「条件式」は次のとおりです。

exp1 -eq exp2
          true if exp1 is numerically equal to exp2.

-eqこれは「算術表現」の両面を作ります。

==適用できる唯一の「条件式」は次のとおりです。

string == pattern
          true if string matches pattern. ....

これにより、左側が文字列(拡張なし?)になり、右側がパターンになります(これらの複雑さを避けるためにすべてが右側で参照されるため、実際に私が思いついたテストでは機能しません。右側がデフォルトです(引用)。 (ここでは算術拡張はありません)。

しかし、たぶん思ったよりも混乱する可能性があります:-)

どう言う?

答え1

からman ksh

算術式は、C言語と同じ構文、優先順位、および式の関連付けを使用します。浮動小数点数量に使用できるすべてのC言語演算子を使用できます。パラメーター拡張構文を使用せずに、算術式で変数を名前で参照できます。変数が参照されると、その値は算術式として評価されます。

条件式は、[[属性をテストするために複合コマンドとともに使用されます。文書比較してひも。との間の単語では、[[フィールド分割やファイル名の生成は行われません]]。各式は、次の単項式または二項式のうちの1つ以上で構成できます。

次の古い算術比較も許可されます。

  • exp1-eqexp2

    • 実際にexp1同じexp2
  • exp1-neexp2

    • 実際にexp1等しくないexp2
  • exp1-ltexp2

    • 実際にexp1未満exp2
  • exp1-gtexp2

    • 実際にexp1それ以上exp2
  • exp1-leexp2

    • 実際にexp1より小さいか等しいexp2
  • exp1-geexp2

    • 実際にexp1より大きいか等しいexp2

そこにある文書は算術への言及が一貫しています。表現心配になり、(とても丁寧な姿が見られます)定義に対する矛盾を避ける[[ 複合コマンド ]]~について文字列比較明示的にまた許可一部役に立たない算術比較同じ文脈で。


からman bash

[[expression]]

  • 状態を返す0か、1条件式の評価に依存します。expression。式は、以下の基本色で構成されています...[[との間の単語では、単語の区切りとパス名の拡張は行われません]]~チルダ拡張、パラメータおよび${変数拡張、算術拡張、コマンド置換、プロセス置換、および引用の削除が実行されます。基本演算子として認識されるには、引用符を解く必要があるなどの条件付き演算子...}$$(())$()<()"\'-f

変える次の形式のステートメントとして割り当てることができます。

  • name=[value]

もしvalue指定しない場合、変数に空の文字列が割り当てられます。すべての値は、~チルダ拡張、${パラメータ}および$変数拡張、$(コマンド置換)$((算術拡張))、および"\'引用符の削除です。変える持っている整数属性設定してからvalue$((算術式として評価されます))$((...))拡張機能は使用されていません...

シェルは算術を可能にしますexpressions場合によっては、評価するには...評価は固定幅整数で行われ、オーバーフローは確認されませんが、ゼロで除算することはキャッチされ、エラーとして表示されます。演算子とその優先順位、結合性、値はC言語と同じです。

シェル変数はオペランドとして受け入れられます。パラメータ拡張は式の評価前に行われます。中expression、シェル変数は、パラメータ拡張構文を使用せずに名前で参照することもできます。変数の値は算術的に評価されます。expression参照時または整数属性が割り当てられた変数にdeclare -i値が割り当てられるとき...シェル変数は、式で使用するために整数属性をオンにする必要はありません。

ホームフレーズexpressions使用される[[ 複合コマンドそしてtest[ 組み込みコマンドファイルのプロパティをテストし、文字列と算術比較を実行します。

arg1OParg2

  • OP-eq、、、、、-neまたはいずれ-lt-leです。これらの算術バイナリ演算子は、次の場合にtrueを返します。-gt-gearg1等しい、等しくない、小さい、小さい、等しい、大きい、大きい、または等しいarg2、それぞれ。arg1そしてarg2正または負のどちらでもかまいません。

これらすべての背景を考慮すると、文書に明示的に可能性が明記されていなくても、観察した動作が意味があると思います。文書には特別な取り扱いが記載されています。パラメータそして整数属性、そして違いを明確に表現します。複合コマンドそして組み込みコマンド

[[比較的通事論taskと同じ意味name=valueはい通事論またはcasewordin...はい通事論。ただし、test合計は[これではなく、パラメータを持つ別々のプロセスです。違いを実際に理解する最善の方法は、シェルエラー出力を見ることです。

set   '[[ \\ -eq 0 ]]' '[ \\ -eq 0 ]'
for    sh in   bash ksh
do     for     exp
       do     "$sh" -c  "$1||$2"
               set "$2" "$1"
done;  done

bash: [[: \: syntax error: operand expected (error token is "\")
bash: line 0: [: \: integer expression expected
bash: line 0: [: \: integer expression expected
bash: [[: \: syntax error: operand expected (error token is "\")
ksh: \: arithmetic syntax error
ksh: [: \: arithmetic syntax error
ksh: \: arithmetic syntax error

2つのシェルは例外を異なって扱いますが、2つのシェルの違いの根本原因は非常に似ています。

  • bash[[ \\ケースを直接呼び出す文法エラー- たとえば、同じ方法で存在しないファイルからリダイレクトする場合 - その時点で開始されますが、(私の考えでは間違っていた)||or式の反対側を評価します。bash する[[表現をしてみてくださいコマンド名エラー出力にあるがコマンドのように呼び出された行番号については説明しません[。期待していた情報を受け取っていないとbash文句を言う[整数式しかし、[[実際には議論を必要とせず、決してそれを必要としないので、そのように文句を言う必要はありません。予想される拡張自体で解析されれば、何でも可能です。

  • ksh構文エラーがある場合は完全に停止し、[[まったく気にしないでください。[両方に対して同じエラーメッセージを記録しますが、[1つが割り当てられています。コマンド名そこ[[ksh[コマンドラインは正常に解析され、拡張が発生した後にのみ呼び出されます。独自の小さなgetoptsルーチンを実行し、独自のルーチンとarg[0c]残りのルーチンを取得しますが、デフォルトの[[シェル構文として再び処理されます。

ドキュメントはこれらの用語を使用しているので、bashバージョンより少し明確ではないと思います。ksharg[12]代わりにexpression[[整数比較に関しては、 、[testと がその瞬間に共にクラスタ化されており、後者の 2 つが実際に必要であるためそうなったようです。議論前者は1つだけ受け取りました。expression

いずれにしても、整数比較は以下で行われる。通事論状況に応じて、基本的に有効な数学演算を実行できます。expression:

   m=5+5  a[m]=10
[[     m   -eq 10 ]] &&
[[     m++ -eq 10 ]] &&
[[     m-- -gt 10 ]] &&
[[ ${a[m]}  == 10 ]] &&
echo "math evals"

math evals

答え2

これはよく文書化されていますbash。たとえば、次のようになります。

   [[ expression ]]
          [...] Word splitting and pathname expansion
          are not performed on the words between the [[ and ]];
          tilde expansion, parameter  and  variable  expansion,
          arithmetic  expansion, command substitution, process 
          substitution, and quote removal are performed.

またはzsh:

    CONDITIONAL EXPRESSIONS
          A  conditional expression is used with the [[ compound
          command to test...
          [...]
          In  the  forms  which  do numeric comparison,
          the expressions exp undergo arithmetic
          expansion as if they were enclosed in $((...)).

答え3

[[POSIX機能ではなくksh88機能です。

何が起こっているのか知りたい場合は、ksh文書を読む必要があります。

この機能について学びたいと思うので、これは組み込みのコマンドではなくシェル構文の一部であるため、コマンドとはまったく異なるベースで機能することに[[注意してください。[[[test

したがって、たとえば、[[ $var == *test? ]]右側のパターンを引用符で囲む必要はありません。

関連情報