根据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
)为单词[
,-n
和]
。这是 的单参数版本test
,它测试该单个参数是否非空。该字符串-n
不为空,因此测试为真。
在 GNU 手册页中,在您引用的段落之后提到了这一点:
-n STRING
the length of STRING is nonzero
STRING equivalent to -n STRING
问题当然是缺乏引用,例如为什么我的 shell 脚本会因为空格或其他特殊字符而卡住?和什么时候需要双引号?
请注意,在不带引号的情况下,不仅空字符串会被破坏。如果var
包含多个单词也会出现问题:
$ var='foo bar'; [ -n $var ]
bash: [: foo: binary operator expected
或通配符:
$ var='*'; [ -n $var ]
bash: [: file.txt: binary operator expected
答案2
-n
不适用于未加引号的变量。
正如联机帮助页所示,-n
测试非零长度字符串。
因此,当测试变量是否使用它扩展为空时,我们必须引用该变量。
所以这个问题的解决方法是[ -n "${peopkg}" ]
答案3
是的,似乎没有字符串不为空。但无论如何你都应该引用变量,因为值有空格。
例如
a="hello, world"
b=""
test -n "$a"
test -n "$b"