Ubuntu 16.04を使用して#!/bin/bash
評価されたコマンドが必要です。
- 直接出力を提供
- 出力を変数にインポートする
- 評価結果の確認
# valid command
foo=$(eval "ls" | tee /dev/tty);
echo ${PIPESTATUS[@]}
echo $foo
# invalid command
foo=$(eval "ls -ßnonsense" | tee /dev/tty);
echo ${PIPESTATUS[@]}
echo $foo
PIPESTATUS
私の問題は意味のある結果を得たとき
- 完全に削除しました
tee /dev/tty
(それ以外の場合は、最初のパイプラインコマンドの一部としてすべての評価失敗をマスクします)。 - または括弧の外に入れてください
foo=$(eval "ls" ) | tee /dev/tty;
- ...しかし、この場合、もはや直接出力または$ foo出力を取得できません。
答え1
代わりに使用してくださいzsh
:
shell_code='ls' # or ls -ßnonsense...
{ foo=$(eval " $shell_code" >&1 >&3 3>&-); } 3>&1
print -r status=$? output=$foo
ここでは、元のstdout(スクリプトがリダイレクトなしで端末で実行されている場合は制御ttyのみ)をfd 3にコピーし、出力をコマンド置換とfd eval
3にリダイレクトしますtee
使用)。 。
サポートされている他のシェル(Linux / Cygwinではksh93ではありません)があるシステムでは、bash
次のことができます。pipefail
/dev/fd/<n>
shell_code='ls' # or ls -ßnonsense...
{
foo=$(
set -o pipefail
eval " $shell_code" 3>&- |
tee 4>&1 >&3 3>&- /dev/fd/4
)
} 3>&1
printf 'status=%s output=%s\n' "$?" "$foo"
open の場合、pipefail
パイプの終了状態は、パイプで失敗した一番右のコマンドの終了状態です。失敗しないeval
限り、ここにありますtee
。
eval
無条件の終了ステータスを取得するには、次のものをbash
使用できます。
shell_code='ls' # or ls -ßnonsense...
{
foo=$(
eval " $shell_code" 3>&- |
tee 4>&1 >&3 3>&- /dev/fd/4
exit "$PIPESTATUS"
)
} 3>&1
printf 'status=%s output=%s\n' "$?" "$foo"
これらの方法では、tee
stdoutは生のstdoutであり、コマンド置換はパイプを介して提供されます/dev/fd/4
。私たちは別の方法(tee
コマンド代替パイプにstdoutを送信し、いくつかのコマンドを介して元のstdoutに書き込む/dev/fd/<n>
)の代わりにこれを行います。これにより、コードがより複雑になりますが、後者がLinuxで動作しないことを避けます。あるいは、Cygwinシステムで開くことは/dev/fd/<n>
fdをコピーするのと同じではありません<n>
(ただし、コマンドの置き換え(ソケットペアを使用するksh93ではない)などのパイプの書き込みの終わりを指すfdに対してこれを行うことは機能的に同じです) 。
答え2
bash
これは、、、、、(Bourne)および次にテストされたほとんどの(すべてではありdash
ませんが)Bourne構文シェルで動作する移植可能なソリューションです。ksh93
ksh88
ash
sh
zsh
for command in "ls -ßnonsense" "ls -ld /tmp"; do
foo=`{ eval "$command"; echo $? > /tmp/ps.$$; } | tee /dev/tty;`
st=`cat /tmp/ps.$$;rm /tmp/ps.$$`
echo "foo=$foo status=$st"
done