Bash

在命令替換中設置的訪問變數

  • May 10, 2017

我寫了一個簡單的腳本

#!/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]}

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