Shell

為什麼即使變數為空,test -n 也會返回 true?我究竟做錯了什麼?

  • February 18, 2020

根據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。

如果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

引用自:https://unix.stackexchange.com/questions/568241