Bash
在命令替換中設置的訪問變數
我寫了一個簡單的腳本
#!/bin/bash -x selentry=`ls -l / | sort ; ts=${PIPESTATUS[0]}` echo $ts
但 $ ts show nothing. How I can display $ ts 變數,或者如何從變數中的命令獲取退出狀態程式碼?
selentry=`ls -l / | sort`
在:
selentry=`ls -l / | sort ; ts=${PIPESTATUS[0]}`
與更現代的相同:
selentry=$(ls -l / | sort ; ts=${PIPESTATUS[0]})
裡面的程式碼在
$(...)
子shell環境中執行(在bash
和 以外的shell的情況下ksh93
,它甚至在不同的shell程序中執行)。因此,對該子 shell 中的變數所做的任何修改都不會影響父 shell。當你這樣做時:
var=$(cmd)
然而,退出狀態
cmd
在$?
. 在以下情況下,這並不適用於$PIPESTATUS
:var=$(foo | bar)
只包含一個值(子shell的退出程式碼,這裡將是退出狀態
bar
(除非pipefail
選項打開,在這種情況下,如果它不為零,它可能是退出狀態)。在數組foo
的位置更糟糕不受分配命令的影響。zsh``$pipestatus
但是,在這裡,如果您不關心
sort
(子shell)的退出狀態,您可以這樣做:selentry=$(ls -l / | sort; exit "${PIPESTATUS[0]}") ts=$?
在這裡,您還可以這樣做:
exec 3< <(ls -l /) # here ls is started as an asynchronous command ls_pid=$! selentry=$(sort <&3) sort_status=$? wait "$ls_pid" exec 3<&- # close that fd 3 ls_status=$?
甚至:
{ selentry=$(sort) sort_status=$? wait "$!" ls_status=$? } < <(ls -l /)
關於讓變數賦值在命令替換中倖存的更一般的問題,在 中
ksh93
,您可以使用${ cmd;}
命令替換的形式(ksh93
雖然不支持$PIPESTATUS
/$pipestatus
)。var=${ foo; c1=$? bar; c2=$? }
在其他類似 Bourne 的 shell 中沒有等價物,您需要通過其他方式(如臨時文件)傳遞數據:
var=$( foo; echo "c1=$?" > "$tempfile" bar; echo "c2=$?" >> "$tempfile" ) . "$tempfile"
或者在這裡:
selentry=$( ls -l / | sort typeset -p PIPESTATUS | sed '1s/PIPESTATUS/my_&/' > "$tempfile" } . "$tempfile" ls_status=${my_PIPESTATUS[0]}