[-n]のように[-n]が偽ではないのはなぜですか?


20

私の質問は、このコードによって生成される戻り値に関するものです。

if [ -n ]; then echo "true"; else echo "false"; fi

これは印刷されtrueます。

[ -z ]また、印刷物を使用した補完テストtrue

if [ -z ]; then echo "true"; else  echo "false"; fi

上記のコードでは、なぜない[ -n ]テストがnullではないとして、すべてで渡されていない文字列値を想定しますか?

以下のコードが印刷されfalseます。これは、渡された文字列値がnullで長さがゼロであるため予想されます。

if [ -n "" ]; then echo "true"; else  echo "false"; fi

回答:


14

[xは]と等価である[ -nX]場合でも、xはで始まる-一切のオペランドがありません提供します。

$ [ -o ] ; echo $?
0
$ [ -eq ] ; echo $?
0
$ [ -n -o ] ; echo $?
0
$ [ -n -eq ] ; echo $?
0

4
なお、歴史的に、[ -t ]stdoutがターミナル(のために短いものだったかどうかをテストしていた[ -t 1 ])と一部のシェルは、まだ(の場合にはそれをやっているksh93ことは、ときにのみ-t、それが使用することをお勧めしますので、リテラルである)[ -n "$var" ]より[ "$var" ]。それはまだいくつかの古いに失敗するであろうけれどもtestの値の実装$varのような=、その場合には、[ "" != "$var" ]あるいは[ "x$var" != x ]またはcase $x in "")...より良いかもしれません。
ステファンシャゼラス

3
-oここの興味深い選択。のような一部のシェルbash-oは、単項演算子(オプションが設定されている場合のテスト)と二項演算子(または)の[ ! -o monitor ]両方であるため、そのようなものはあいまいです。それがいることをテストしているmonitorオプションが設定され、またはそのいずれかされていない!か、monitor空でない文字列でありますか?POSIXルールは、後者を決定します(これはと異なります[[ ! -o monitor ]])。
ステファンシャゼラス

30

[ -n ]-nテストを使用しません。

-n中には、[ -n ]すべてのテストではありません。[との間に引数が1つしかない場合]、その引数は空かどうかを確認するためにテストされる文字列です。文字列の先頭-にがある場合でも、テストではなくオペランドとして解釈されます。文字列以来-n空でない-それは2つの文字が含まれている、-nないゼロcharacters-- [ -n ]TRUEと評価。

以下のようイグナシオバスケス-エイブラムス氏は述べています。ここで、string単一の引数で、テストは上で実行string中で、その上に実行されるテストと同じです。である場合、特別なことは何も起こりません。第二で単に空虚のためにテストされている文字列です。[ string ][ -n string ]string-n-n[ -n ]-n[ -n -n ]

[との間に引数が1つしかない場合]、その引数は、テストと同じ名前が付けられたとしても、常に空でないかどうかをテストする文字列です。同様に、との間に2つの引数が[あり]、最初の引数がである-n場合、2番目の引数は、テストと同じ名前が付けられた場合でも、常に空でないことをテストする文字列です。これは、単純に、前後の[単一の引数が文字列オペランドである[と主張するためです。]-n

同じ理由で[ -n ]使用していない-nテストを、[ -z ]使用しない-zテストを。


あなたはについての詳細を学ぶことができる[bashそれのヘルプを調べることによって。それは組み込みシェルであることに注意してください:

$ type [
[ is a shell builtin

したがって、実行help [してヘルプを取得できます。

$ help [
[: [ arg... ]
    Evaluate conditional expression.

    This is a synonym for the "test" builtin, but the last argument must
    be a literal `]', to match the opening `['.

どのテストがサポートされているか、どのように機能するかなどの詳細については、ヘルプを参照する必要がありtestます。コマンドを実行するとhelp test、詳細なリストが表示されます。すべてを再現するのではなく、文字列演算子に関する部分を次に示します。

      -z STRING      True if string is empty.

      -n STRING
         STRING      True if string is not empty.

      STRING1 = STRING2
                     True if the strings are equal.
      STRING1 != STRING2
                     True if the strings are not equal.
      STRING1 < STRING2
                     True if STRING1 sorts before STRING2 lexicographically.
      STRING1 > STRING2
                     True if STRING1 sorts after STRING2 lexicographically.

ことに注意してください-n STRINGとだけSTRING文字列があれば、彼らはテスト:同じことを行うSTRING空ではありません。



1
:たぶんまた、これは、このように、設定を解除している非引用された変数のための意味合いを持っていることを言及paste.ubuntu.com/25831047
Sergiy Kolodyazhnyy

1
@SergiyKolodyazhnyy別の答えの方がいいかもしれません。設定されていない、または設定されているが空である、またはIFS空白のみを含む変数は、それを行います。ゼロではなく複数の単語を含む変数は別の効果を生み、まったく異なるテストが実行される可能性があります。オペランドであることを意図して文字通り表示される文字列は、スペースやタブが含まれていない場合、または引用符で囲まれている場合にのみ適切に機能します。このトピックをアクセシブルな方法で説明すると、答えははるかに長く複雑になります。回答を投稿することに決めた場合は、こちらからお気軽にお問い合わせください。
エリアケイガン

@Eliah Kagan、Ignacio Vazquez-Abramsの回答は私の質問に答えましたが、あなたの答えはより完全で詳細です。
ラヴィクマール

1
私はあなたがそれがそうであり、この方法でなければならない理由を逃していると思います:そうでなければ、に展開さ[ "$var" ]れる可能$var性があるため、テストとして決して使用できません-n
R ..

12

[ -n ][コマンド(別名testコマンド)は、指定された引数のに基づいて動作するため、true です。引数が1つだけ指定されている場合、引数が空でない文字列であれば結果は「true」になります。「-n」は2文字の文字列で、空ではないため、「true」です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.