次のBASH Shellエラーの意味を説明して修正するための単純明快なリソースが1つも見つからなかったので、調査の結果、投稿したものを投稿しました。
エラー:
-bash: [: too many arguments
Googleにやさしいバージョン:bash open square bracket colon too many arguments
。
Context:等号、等のような単純な比較演算子を含む単一の角括弧内のif条件。例えば、
VARIABLE=$(/some/command);
if [ $VARIABLE == 0 ]; then
# some action
fi
$VARIABLE
がスペースまたは他の特殊文字を含む文字列である場合、 および単一の大括弧が使用されます (これはtest
コマンドのショートカットです)では、文字列は複数の単語に分割されます。これらはそれぞれ別々の引数として扱われます。
つまり、1つの変数が多くの引数に分割されます。
VARIABLE=$(/some/command);
# returns "hello world"
if [ $VARIABLE == 0 ]; then
# fails as if you wrote:
# if [ hello world == 0 ]
fi
スペースや他の特殊文字を含む文字列を出力する関数呼び出しについても同じことが言えます。
変数の出力を二重引用符で囲み、1つの文字列(つまり1つの引数)のままにします。例えば、
VARIABLE=$(/some/command);
if [ "$VARIABLE" == 0 ]; then
# some action
fi
そのように単純です。ただし、変数が空文字列にならないことも保証できない場合は、以下の「また注意してください」に進んでください。または空白文字しか含まない文字列。
あるいは、代替の修正は二重角括弧を使用することです(これはnew test
コマンドのショートカットです)。
これはbash(そして明らかにkornとzsh)にのみ存在し、/bin/sh
などによって呼ばれるデフォルトシェルと互換性がないかもしれません。これは例えば、コンソールからはうまくいくがcron
からはうまくいかないかもしれませんすべての設定方法.
これは次のようになります。
VARIABLE=$(/some/command);
if [[ $VARIABLE == 0 ]]; then
# some action
fi
[: unary operator expected
エラーにも注意してください「引数が多すぎる」というエラーが表示される場合は、予測不可能な出力を含む関数から文字列を取得している可能性があります。 空の文字列(またはすべての空白文字列)を取得することも可能であれば、これは上記の "クイックフィックス"でもゼロ引数として扱われます。そして[: unary operator expected
で失敗します
他の言語に慣れていても、それは同じ「問題」です。評価される前に、変数の内容がこのようなコードに効果的に表示されることは期待できません。
これは[: too many arguments
と[: unary operator expected
の両方のエラーを防ぐ例です。出力が空の場合はデフォルト値(この例では0
)で置き換え、全体を二重引用符で囲みます。
VARIABLE=$(/some/command);
if [ "${VARIABLE:-0}" == 0 ]; then
# some action
fi
(ここでは、$ VARIABLEが0の場合、または空の場合にアクションが発生します。当然、異なる動作が必要な場合は、0(デフォルト値)を別のデフォルト値に変更する必要があります。
最後の注意:[
はtest
のショートカットなので、エラーtest: too many arguments
(およびtest: unary operator expected
)についても上記のすべてが当てはまります。
2つの変数がbothempty(またはnon-empty)であるかどうかをテストしようとすると、同じエラーが発生し、この記事に飛び込んできました。それは 複合比較 - 7.3であることが判明しました。その他の比較演算子 - 高度なBashスクリプトガイド ;そして私は次の点に注意すべきだと思いました:
-e
-z
を使用します(String)test
sと&&
をそれらを使ってください:[ ... ] && [ ... ]
test
で-a
演算子を使用します。[ ... -a ... ]
これが有効なコマンドです(ディレクトリ内のすべてのtxtファイルを検索し、grep
が見つけたファイルをダンプするには、2つの単語が両方含まれています)。
find /usr/share/doc -name '*.txt' | while read file; do \
a1=$(grep -H "description" $file); \
a2=$(grep -H "changes" $file); \
[ ! -z "$a1" -a ! -z "$a2" ] && echo -e "$a1 \n $a2" ; \
done
2013年8月12日編集:関連問題メモ:
古典的なtest
(一重角括弧[
)で文字列の等価性をチェックするとき、あなたはMUSTの間にスペースが必要です。この場合、単数形の「等しい」=
記号です(ただし、2つの等しい記号==
も、等価演算子として受け入れられているようです)。したがって、これは(黙って)失敗します。
$ if [ "1"=="" ] ; then echo A; else echo B; fi
A
$ if [ "1"="" ] ; then echo A; else echo B; fi
A
$ if [ "1"="" ] && [ "1"="1" ] ; then echo A; else echo B; fi
A
$ if [ "1"=="" ] && [ "1"=="1" ] ; then echo A; else echo B; fi
A
...しかし、スペースを追加してください - そして、すべてがよさそうです:
$ if [ "1" = "" ] ; then echo A; else echo B; fi
B
$ if [ "1" == "" ] ; then echo A; else echo B; fi
B
$ if [ "1" = "" -a "1" = "1" ] ; then echo A; else echo B; fi
B
$ if [ "1" == "" -a "1" == "1" ] ; then echo A; else echo B; fi
B
誤ってキーボードに触れてスペースを空けた場合もあります。
if [ "$myvar" = "something"]; then
do something
fi
このエラーメッセージが表示されます。 ']'の前のスペースが必要です。
[: too many arguments
または[: a: binary operator expected
エラーが発生する可能性がある別のシナリオは、すべての引数"$@"
をテストしようとした場合です。
if [ -z "$@" ]
then
echo "Argument required."
fi
foo.sh
またはfoo.sh arg1
を呼び出すと、正常に機能します。ただし、foo.sh arg1 arg2
のような複数の引数を渡すと、エラーが発生します。これは、有効な構文ではない[ -z arg1 arg2 ]
に展開されているためです。
引数の存在を確認する正しい方法は、[ "$#" -eq 0 ]
です。 ($#
は引数の数です)。
私は自分のスクリプトで同じ問題を抱えています。しかし、私がいくつかの修正をしたとき、それは私のために働いた。私はこれが好きでした: -
export k=$(date "+%k");
if [ $k -ge 16 ]
then exit 0;
else
echo "good job for nothing";
fi;
そのようにして私は自分の問題を解決した。それがあなたにも役立つことを願っています。