test(1)
マニュアルページによると:
-n STRING
the length of STRING is nonzero
だから私はこれがうまくいくと期待しました。
[ -n ${var} ] && echo "var is not empty"
このロジックを実際のケースで使用しましたが、スクリプトは次のようになります。
[...]
dne() {
echo DEBUG: wc -c: $(echo -n $peopkg |wc -c)
echo DEBUG: pdir: $pdir
echo "Error: ${package}: doesn't exist in local repos"
exit 1
}
# packages are listed as such:
# p/pname/package-version-release-distrelease...
# pname is inconsistent, but it is guaranteed that the first word in package
# (all to lowercase) will match at least one pname.
# NOTE: package-[0-9]* matches package-32bit. *-32bit is a subpackage we want
# to match later, but not when it's not already in pcase.
# So that must be negated too
pfirst=${pcase%%-*}
for pdir in ${p}/${pfirst}*
do
# check if the glob matched anything at all
[ ${pdir} = "${p}/${pfirst}*" ] && dne
peopkg=$(find ${pdir} \
-name ${package}-[0-9]* \
! -name *.delta.eopkg \
! -name ${package}-32bit* |sort -rn |head -1)
echo DEBUG: in-loop peopkg: $peopkg
echo DEBUG: in-loop wc -c: $(echo -n $peopkg |wc -c)
echo DEBUG: in-loop test -n: $(test -n $peopkg && echo true || echo false)
#------------------------------------------------------------#
# break on ANY match. There's supposed to be only one anyway #
[ -n ${peopkg} ] && break # <--- [issue here] #
#------------------------------------------------------------#
done
[ -z ${peopkg} ] && dne
[...]
ここで重要なのは、実行すると次のメッセージが表示されることです。
DEBUG: in-loop peopkg:
DEBUG: in-loop wc -c: 0
DEBUG: in-loop test -n: true
DEBUG: wc -c: 0
DEBUG: pdir: a/alsa-firmware
Error: alsa-utils: doesn't exist in local repos
これは私には理解できません。DEBUG: pdir: a/alsa-firmware
ループが常に最初の反復で終了することを示します。これは、globパターンa / alsa *が何かと一致し、peopkgの長さがゼロ以外の場合にのみ発生します。
PS:私はPOSIXの互換性を研究しています。
答え1
var
空の文字列が含まれている場合([ -n $var ]
トークン化後$var
)、単語に展開されます[
。これは、単一のパラメータがnullでないことをテストする単一のパラメータバージョンです。文字列が空ではないため、テストはtrueです。-n
]
test
-n
GNU のマニュアルページでは、引用した段落の後にこの内容が記載されています。
-n STRING
the length of STRING is nonzero
STRING equivalent to -n STRING
もちろん、問題は引用が不足していることです。スペースやその他の特殊文字が原因でシェルスクリプトが停止するのはなぜですか?そしていつ二重引用符が必要ですか?
引用符がないと、空の文字列だけが破損するわけではありません。var
複数の単語が含まれている場合でも問題が発生する可能性があります。
$ var='foo bar'; [ -n $var ]
bash: [: foo: binary operator expected
またはワイルドカード:
$ var='*'; [ -n $var ]
bash: [: file.txt: binary operator expected
答え2
-n
引用符がない変数には機能しません。
マンページに示すように、-n
ゼロ以外の長さをテストします。ひも。
したがって、変数を使用してnullに拡張されているかどうかをテストするときは、変数を参照する必要があります。
だからこの問題の解決策は[ -n "${peopkg}" ]
答え3
はい、空でない文字列がないようです。ただし、値にスペースがあるため、変数を引用する必要があります。
例えば
a="hello, world"
b=""
test -n "$a"
test -n "$b"