Shell
為什麼即使變數為空,test -n 也會返回 true?我究竟做錯了什麼?
根據
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