Bash

這是bash中的錯誤嗎?如果從管道呼叫,return 不會退出函式

  • September 19, 2015

我最近在使用 bash 時遇到了一些奇怪的問題。在嘗試簡化我的腳本時,我想出了一小段程式碼:

$ o(){ echo | while read -r; do return 0; done; echo $?;}; o
0
$ o(){ echo | while read -r; do return 1; done; echo $?;}; o
1

return應該在沒有列印的情況下退出該功能$?,不是嗎?好吧,然後我檢查了我是否可以單獨從管道返回:

$ echo | while read -r; do return 1; done
bash: return: can only `return' from a function or sourced script

沒有while循環也會發生同樣的情況:

$ foo(){ : | return 1; echo "This should not be printed.";}
$ foo
This should not be printed.

我在這裡缺少什麼嗎?Google搜尋沒有帶來任何結果!我的 bash 版本是Debian Wheezy 上的4.2.37(1)-release

相關:https ://stackoverflow.com/a/7804208/4937930

您不能退出腳本或通過子shellexitreturn在子shell 中從函式返回,這不是一個錯誤。它們在另一個程序中執行,不影響主程序。

除此之外,我想您在(可能)未定義的規範上看到了未記錄的 bash 行為。return在一個函式中,子shell命令的頂層沒有錯誤被斷言,它的行為就像exit.

return恕我直言,這是一個 bash 錯誤,它取決於主語句是否在函式中的不一致行為。

#!/bin/bash

o() {
   # Runtime error, but no errors are asserted,
   # each $? is set to the return code.
   echo | return 10
   echo $?
   (return 11)
   echo $?

   # Valid, each $? is set to the exit code.
   echo | exit 12
   echo $?
   (exit 13)
   echo $?
}
o

# Runtime errors are asserted, each $? is set to 1.
echo | return 20
echo $?
(return 21)
echo $?

# Valid, each $? is set to the exit code.
echo | exit 22
echo $?
(exit 23)
echo $?

輸出:

$ bash script.sh 
10
11
12
13
script.sh: line 20: return: can only `return' from a function or sourced script
1
script.sh: line 22: return: can only `return' from a function or sourced script
1
22
23

這不是錯誤,bash而是記錄在案的行為

管道中的每個命令都在其自己的子 shell 中執行

return指令在函式定義中有效,但也在子shell中,它不會影響其父shell,因此下一條指令 ,echo無論如何都會執行。儘管如此,它還是一種不可移植的 shell 結構,因為POSIX 標准允許組成管道的命令在子 shell(預設)或頂部(允許的擴展)中執行。

此外,多命令管道的每個命令都處於子shell環境中;然而,作為擴展,管道中的任何或所有命令都可以在目前環境中執行。所有其他命令都應在目前 shell 環境中執行。

希望您可以bash通過以下幾個選項告訴您按照您期望的方式行事:

$ set +m # disable job control
$ shopt -s lastpipe # do not run the last command of a pipeline a subshell 
$ o(){ echo | while read -r; do return 0; done; echo $?;}
$ o
$          <- nothing is printed here

引用自:https://unix.stackexchange.com/questions/230654