なぜ 'test -z ='がエラーではないのですか?

なぜ 'test -z ='がエラーではないのですか?

私は次の本を持っています。

"...たとえば、シェル変数記号に等号が含まれている場合、

長さがゼロであることをテストしようとすると、何が起こるかを確認してください。

$ echo $symbol
= 
$ test -z "$symbol" 
sh: test: argument expected 

=演算子は-z演算子より優先順位が高いです...」

しかし、Ubuntu(仮想マシンで実行)で試してみると、次のようになります。

jackson@jackson-VirtualBox:/$ symbol="="
jackson@jackson-VirtualBox:/$ echo $symbol 
=
jackson@jackson-VirtualBox:/$ test -z "$symbol"
jackson@jackson-VirtualBox:/$

テストコマンドの結果がなぜ出ないのですsh: test:argument expectedか?

本にエラーがありますか?

答え1

コマンドtestには、引数が演算子かオペランドかを知らせません。たとえば、シェルコードはパラメータを使用してsymbol='='; test -z "$symbol"コマンドを呼び出します。演算子なのか、それともその演算子のオペランドなのかを判断するのはコマンドに依存します。test-z=test-z=

ほとんどの場合、文法的に正しい解釈は最大1つです。たとえば、単項末尾演算子がないため、2つの引数を解析する唯一の方法は、最初の引数が単項接頭辞演算子で、2番目の引数がオペランドの場合です。したがって、これは(is-string-empty)演算子を文字列にtest -z =適用するという意味にすぎません。-z=

3つ以上のパラメータがあると、いくつかの極端なケースが不明になります。たとえば、単純な文字列の合計または括弧内の単純な文字列に演算子を適用test '(' -a ')'できます。 (他の結果を提供する3つの引数を含むあいまいな解析は考えられません。)-a()-a

このコマンドの以前の実装には、短くてtest曖昧ではない場合を許可しないバグを持つパーサーがありました-z =。たとえば、パーサーは、=2 番目の位置が二項演算子であると判断し、演算子に正しいオペランドがないことに気づきました。Sven MascheckのBourneシェルページ問題のある歴史的実装を紹介しますtest -a =。これには、Bourneの実装とkshの古代バージョンが含まれます。

すべての最新の実装は、2〜3つの有効な引数が与えられたときに期待どおりに機能します。これ(そしてそれ以上)は次によって主導されます。POSIX

このコマンドは、最終パラメータとしてaが必要であることを除いて同じコマンドであるため、[同じ欠陥があります。test]

いくつかの最新のシェル(ksh、bash、zsh)で利用可能なシェル構文は、[[ … ]]シェル内で異なる方法で解析されるため、同じ問題はありません。は文字列に適用される演算子[[ -z "$symbol" ]]として解析されます。値が等号の場合でも、その単語はコマンドに文字通り表示されないため、演算子を参照できません。-zsymbol==

test -z "$symbol"サプライヤーがまだサポートしていない(またはいくつかのまれなニッチ業界で何らかの形でまだサポートされている)古代のシステムを使用しない限り、現実の世界で詰まっているシェルには会いません。本でこれについて言及している場合は、より良いリソースを使用することをお勧めします。より良い本は第三世界の国では非常に高価ですが、インターネットには無料で提供されるものがたくさんあり、その一部は実際には良い本です。

関連情報