bash: [: 変数 [duplicate] にテストを保存するときに `]' がありません。

bash: [: 変数 [duplicate] にテストを保存するときに `]' がありません。

これが機能する理由:

[ -r /tmp ] && echo "tt" >/tmp/taa
cat taa
tt

しかし、次はそうではありません。どうすればこの問題を解決し、再利用のための変数を維持できますか?

COMD='[ -r /tmp ] && echo "tt"'
$COMD >/tmp/taa
bash: [: missing `]

ありがとう

編集:evalうまくいきます。しかし、私はその理由を理解していません。質問、私は重複としてマークされています、説明がありません。また、&&次から始まる部分を削除すると機能し、実際には次のことなく正しい結果を返しますeval

COMD='[ -r /tmp ]'
$COMD
echo $?
0

COMD='[ -r /tmpdddd ]'
$COMD
echo $?
1

答え1

あなたは考えないでしょう:

var='echo test && reboot'
echo $var

エクスポートしてtestからやり直しても大丈夫ですか?

代わりに出力されます。echo test && reboot

これは次のような場合に便利です。

var='echo test && reboot'
$var

今、混乱しているのは、ほとんどのBourne様シェルでecho test && rebootコマンドが見つからないというエラーで失敗しないことです。代わりに変更しないと$IFS出力されますtest && reboot

これは、これらのシェルで変数を引用符で囲まないと、一種の分割+グローブ演算子が適用されるためです。

引用符が付けられていないため、単語に分割され$varます(特殊引数に基づいて):$IFS、、、、、、echo実行するコマンドは最初の()に由来し、すべての単語はコマンドに引数として渡されます。引数です。引用符のないリテラルだけが、その言語の演算子として理解されます。 Cと同様に、C言語の構文に演算子が含まれているとしても、2つの引数を渡すわけではありません。test&&rebootecho&&echo&&&&shvar="foo, bar"; printf(var)printfvar,

実際、歴史を振り返ると、1970年代初頭にUNIXの最初のバージョンにさかのぼりますshトンプソンシェル)そこで実行されますrebootsh当時は変数はサポートされていませんでしたが、位置パラメータはありました。

以下は、PDP11エミュレータでUnix V1を使用することです。

$ cat myscript
echo $1
$ sh myscript 'echo test; reboot'
echo test
No command
$ ls -l /bin/sh
total   12
 88 lxrwr-  1 sys    5312 Jan  1 00:00:00 sh

reboot(幸い、当時は命令がなかったためNo commandエラーが発生しました。)

今日の基準では奇妙に聞こえるかもしれませんが、Unix V1は数百キロバイトのメモリとメガバイトの記憶領域を備えたシステムで実行されていたので、当時はすべてを単純に保つ必要がありました。最新のシステム(何も実行しないコマンド)shよりもはるかに小さいことを確認してください/bin/true(私のシステムでは27KB(動的リンカーまたはリンクされた動的ライブラリを除く)、このshの場合は5KB)。

1970年代後半、Unix V7にはsh当時はまだ新しいBourneシェルが搭載されていました。さらに進化してきたが、それでも以前の製品との互換性を完全に破るわけではない。同様の時期にBSDに登場したcshも同様でした。これはおそらくBourneシェルの厄介な動作の主な理由です。解釈するものではありません)、Thomsonシェルと逆互換可能。

または(Bourneシェルと同様)などの一部のシェルは最終的にこの問題を解決しましたが、多くのシェルはrcBourneシェルとの下位互換性を維持します。fishzshbash

文字列をシェルコードとして解釈する場合は、evalこのコマンドの目的は次のとおりです。

eval "$var"

(Bourneなどのシェルで分割+グローブを防ぐために引用符を参照してください)。

しかし、コードを変数に保存するには、他の言語などの関数を使用する方が合理的です。

f() { echo test && reboot; }

答え2

&&変数拡張後は演算子が認識されないためです。引用符も同じです。有効な場合は印刷されます"tt"。 (努力するcmd='echo "tt"'; $cmd:)

関数として作成します。

checktmp() {
    [ -r /tmp ] && echo "tt"
}
checktmp

関数はコード用で、変数はデータ用です。

関連情報