次の式を試みると、bash
奇妙なエラー メッセージが表示されます。
[: -lt: unary operator expected
まず関数の定義
some_func () {
(( 3 + 5 ))
}
そしてその表現
[ $(some_func) -lt 10 ] && true
問題は、-lt
コマンド置換や算術展開などの演算子を混在させることにあると思いますか?
終了コード$?
は2で、メッセージはan unary op was expected
。
答え1
そのはず
some_func() {
echo "$(( 3 + 5 ))"
}
[ "$(some_func)" -lt 10 ]
なぜ失敗したのか
$(some_func)
拡大すると出力関数*(末尾の改行を除く)は何も出力しません。したがって、テストは次のようになります。
[ -lt 10 ]
最も基本的な形態では、テスト[
は1〜3個のパラメータを受け入れます上記には 2 つのパラメータがあるため、Bash は最初のパラメータが単項演算子であると想定します。-lt
はバイナリであるため、エラー メッセージが表示されます。
あなたは適宜拡大部分を引用したと
[ "$(some_func)" -lt 10 ]
テストに空の文字列が含まれるため、エラーは「整数式が必要です」となります。
[ "" -lt 10 ]
そして、重大な状況は&& true
冗長です。
*展開は引用符で囲まれていないため、出力も単語の分割そしてファイル名の拡張$IFS
ただし、デフォルト値から変更されていない限り、これらは現在の例では役割を果たしません。
答え2
$(cmd)
取得する標準出力¹なのでcmd
、それを結果に展開するにはcmd
、出力それ:
some_func() {
echo "$(( 3 + 5 ))"
}
[ "$(some_func)" -lt 10 ]
他の人がすでに言っているように。ただし、これはsome_func
サブシェル環境で実行されることを意味するため、変数やその他の変更は後で失われます。
たとえば、次のようなことは意味がありません。
counter=0
incr() { echo "$((++counter))"; }
while [ "$(incr)" -le 10 ]...
as は$(incr)
常に 1 に展開されます (as はcounter
サブシェル内でのみ増分されます)。
数値結果を返す関数の場合、算術評価、サポートするシェルが必要になります数学関数ksh93
または ではダメですzsh
。bash
でzsh
:
counter=0
incr() (( ++counter ))
functions -M incr
while (( incr() <= 10 )); do
print $counter
done
でksh93
:
function .sh.math.incr i {
# ksh93 functions must take at least one argument
(( .sh.value = (counter += i) ))
}
while (( incr(1) <= 10 )); do
print "$counter"
done
ksh93 または mksh の最新バージョンでの別の代替手段は、サブシェルを導入しないコマンド置換の形式を使用することです。
counter=0
function incr { print "$(( ++counter ))"; }
while [ "${ incr; }" -le 10 ]; do
print "$counter"
done
またはmksh
:
counter=0
incr() (( REPLY = ++counter ))
while [ "${| incr; }" -le 10 ]; do
print "$counter"
done
を含むすべての POSIX シェルでは、定義済みの変数 (そのためには が一般的に使用されます)bash
に常に値を返すことができます。$REPLY
counter=0
incr() { REPLY=$(( counter += 1 )); }
while incr; [ "$REPLY" -le 10 ]; do
echo "$counter"
done
詳細は以下をご覧ください。mkshのvalsub機能に関する別のQ&Aへの回答
¹ 末尾の改行文字とNUL文字が取り除かれ、bash
ここでは引用符を忘れたため、split+globの対象となります。
答え3
コマンド置換出力をキャプチャするコマンドまたは関数の。その関数には出力がありません。
変数$?
は戻りコード機能の。
次のいずれかを実行します。
some_func
(( $? < 10 )) && echo yes
または関数を次のように変更します。
some_func() {
echo $(( 3 + 5 ))
}
[[ $(some_func) -lt 10 ]] && echo yes
[[...]]
の代わりにを使用していることに注意してください[...]
。二重括弧の条件では、空の値に対してより寛容になります。