script - source linux




退出Bash中命令替換的變量賦值代碼 (3)

我很困惑這個命令在明確地執行變量賦值時會返回什麼錯誤代碼並且使用命令替換:

a=$(false); echo $?

它輸出1 ,這讓我認為變量賦值不會掃描或產生最後一個錯誤代碼。 但是當我嘗試這個時:

false; a=""; echo $?

它輸出0 ,顯然這是a=""返回並覆蓋1返回false

我想知道為什麼會發生這種情況,變量賦值中是否存在與其他正常命令不同的特殊性? 或者只是因為a=$(false)被認為是單個命令而且只有命令替換部分才有意義?

- 更新 -

謝謝大家,從答案和評論中我得到了“當您使用命令替換分配變量時,退出狀態是命令的狀態。” (由@Barmar提供),這個解釋非常清晰易懂,但對於程序員來說說話不夠精確,我想從TLDP或GNU手冊頁等權威人士那裡看到這一點的參考,請幫我找到它出來,再次感謝!


(不是原始問題的答案,但評論太長)

注意export A=$(false); echo $? export A=$(false); echo $? 輸出0! 顯然, devnull答案中引用的規則不再適用。 為該引用添加一些上下文(強調我的):

3.7.1簡單的命令擴展

...

如果在擴展後留下命令名稱,則執行如下所述。 否則 ,該命令退出。 如果其中一個擴展包含命令替換,則該命令的退出狀態是執行的最後一個命令替換的退出狀態。 如果沒有命令替換,則命令以狀態為零退出。

3.7.2命令搜索和執行[ - 這是“下面”的情況 ]

IIUC手冊描述了var=foo作為var=foo command...特殊情況var=foo command...語法(非常令人困惑!)。 “最後一個命令替換的退出狀態”規則僅適用於無命令情況。

雖然將export var=foo視為“修改後的賦值語法”很誘人,但它並不是 - export是一個內置命令(恰好採用類似賦值的args)。

=>如果要導出var AND capture命令替換狀態,請分2個階段執行:

A=$(false)
# ... check $?
export A

這種方式也適用於set -e模式 - 如果命令替換返回非0,則立即退出。


在執行命令時, $(command)允許$(command)輸出替換自身

當你說:

a=$(false)             # false fails; the output of false is stored in the variable a

命令false產生的輸出存儲在變量a 。 此外,退出代碼與命令生成的相同。 help false會告訴:

false: false
    Return an unsuccessful result.

    Exit Status:
    Always fails.

另一方面,說:

$ false                # Exit code: 1
$ a=""                 # Exit code: 0
$ echo $?              # Prints 0

導致賦值的退出代碼返回到0

編輯:

引自manual

如果其中一個擴展包含命令替換,則該命令的退出狀態是執行的最後一個命令替換的退出狀態。

引自BASHFAQ/002

如何在變量中存儲命令的返回值和/或輸出?

...

output=$(command)

status=$?

output的賦值對command的退出狀態沒有影響,退出狀態仍在$?


請注意,在函數中使用local時不是這種情況。 這是與接受的答案中描述的微妙不同的行為,以及此處發布的鏈接: BASHFAQ/002BASHFAQ/002

以這個bash腳本為例:

#!/bin/bash
function funWithLocalVar() {
    local output="$(echo "Doing some stuff.";exit 1)"
    local exitCode=$?
    echo "output: $output"
    echo "exitCode: $exitCode"
}

function funWithoutLocalVar() {
    output="$(echo "Doing some stuff.";exit 1)"
    local exitCode=$?
    echo "output: $output"
    echo "exitCode: $exitCode"
}

funWithLocalVar
funWithoutLocalVar

這是這個的輸出:

nick.[email protected]-laptop1:~$ ./tmp.sh 
output: Doing some stuff.
exitCode: 0
output: Doing some stuff.
exitCode: 1

也許沒有人關心,但我做到了。 我花了一分鐘時間弄清楚為什麼我的狀態代碼總是為0時顯然不是。 不是100%明白為什麼。 但只知道這有幫助。







exit-code