bash 中是否有區別,或語句否定的首選用法?
if ! [[ -z "${var}" ]]; then
do_something
fi
相對
if [[ ! -z "${var}" ]]; then
do_something
fi
答案1
! [[ expression ]]
如果整個測試傳回 false,則為 true
[[ ! expression ]]
如果單一表達式傳回 false,則該值為 true。
由於測試可以是複合表達式,因此這可能非常不同。例如:
$ [[ ! 0 -eq 1 || 1 -eq 1 ]] && echo yes || echo no
yes
$ ! [[ 0 -eq 1 || 1 -eq 1 ]] && echo yes || echo no
no
就我個人而言,我更喜歡在適用的情況下在測試構造內部使用否定,但根據您的意圖,在外部也完全可以。
答案2
A! cmd
其實是一個管道,並且!
否定退出代碼所有的管道。
來自 man bash:
管道 管道是由一個或多個指令組成的序列,由一個控制運算子 | | 分隔開。或|&。管道的格式為:
[time [-p]] [ ! ] command [ [|||&] command2 ... ]
....
如果保留字!在管道之前,該管道的退出狀態是如上所述的退出狀態的邏輯非。 shell 在傳回值之前等待管道中的所有命令終止。
從這個意義上說,a:
! [[ 2 -eq 2 ]]
!
是整個退出代碼的否定 ( ) [[
(一旦全部執行完畢)。因此,退出代碼為 0:
! [[ 2 -eq 2 && 3 -eq 4 ]]
然而
A[[ ! ]]
是一個複合命令(不是管道)。來自 man bash:
複合指令
...
[[ 表達式 ]]
根據條件式表達式的計算結果傳回 0 或 1 狀態。
表達式由下面條件表達式中所述的主要元素組成。
因此,退出代碼為 1:
[[ ! 2 -eq 2 && 3 -eq 4 ]]
因為這其實相當於:
[[ ( ! 2 -eq 2 ) && ( 3 -eq 4 ) ]]
透過短路求值, 的右邊&&
永遠不會被求值,實際上等價於這個短得多的表達式:
[[ ! 2 -eq 2 ]]
這永遠是錯的(1)。
簡而言之:裡面[[
,!影響部分的表達式。
首選
使用!
內部[[
更為常見(並且可以移植到更多 shell(使用)),但如果沒有透過明智地使用 來明確控制來界定否定的範圍(這可能會成為構造內部的問題),[
有時可能會造成混亂。()
[
但是(在 bash、ksh 和 zsh 中)的結果! [[
定義非常明確且更容易理解:執行整個過程[[
並否定結果。
應該使用哪一個是個人喜好(和理解)的問題。