テスト式でのパラメータ拡張は可能ですか?

テスト式でのパラメータ拡張は可能ですか?

次の式を試みると、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または ではダメですzshbash

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

[[...]]の代わりにを使用していることに注意してください[...]。二重括弧の条件では、空の値に対してより寛容になります。

関連情報