bash條件測試之Null 字元串的困惑,bash條件字串
看一個字串是否為空白,可以通過 -n 或 -z來判斷。按照操作符的意義,變數VAR而言,如果VAR為空白或未定義,那麼-n測試結果應該為假,而-z應該為真。反之,如果不空,則-n為真,-z為假。
採用條件測試的列表形式,即“[ -n $VAR ] && echo TRUE”,如果輸出TRUE,則表明條件測試結果為真。
經過測試,顯然VAR不空時,測試結果都正常,而VAR為空白,測試結果也是真,但很多手冊指南什麼的(包括ABS《Advance Bash Scripting Guide》的樣本7.1),都說這個應該可以正常工作,原因何在?
將上面語句寫入指令碼,並用bash -x 執行,發現測試條件成為了“'[' -n ']'”,也就是說經過分詞處理之後, 為空白的變數實際上消失了,測試命令變成了只有“-n”這麼一個參數,而查bash手冊(bash4.2)中關於test(與'['命令等價, 注意“[”實際上是一個命令)命令求值的解釋,發現只有一個參數而且參數不空的時候,求值都為真。也就是說,將 “-n”換成別的什麼測試操作符,比如“-z”或“-e”,測試結果都是真。一試,果不其然。
解決辦法是什麼呢?
方法一,不直接使用變數${VAR},而是後面附加一個任一字元,然後比較與此字元是否相等來測試,變數是否為空白。 比如“[ ${VAR}y == y ] && echo TRUE”,會輸出TRUE,而“[ ${VAR}y != y ] && echo TRUE”就不會輸出。
方法二,使用“if [[ conditional-expression ]] ”的形式。其中“[[”是關鍵字而不是命令。這種形式下“[[ ... ]]”不會 進行分詞處理,所以用bash -x執行指令碼,發現“[[ -n $VAR ]]”成了“[[ -n '' ]]”,就是說空串依然作為一個參數(即'')儲存下來了,根據test的求值規則,這是兩個參數了,所以測試操作符就能正常工作了。這樣一看,ABS強調盡量用“[[ ... ]]”結構還是很有道理的。