首選

首選

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 中)的結果! [[定義非常明確且更容易理解:執行整個過程[[並否定結果。

應該使用哪一個是個人喜好(和理解)的問題。

相關內容