コマンド置換に設定されたアクセス変数

コマンド置換に設定されたアクセス変数

簡単なスクリプトを書いた

 #!/bin/bash -x
 selentry=`ls -l / | sort ; ts=${PIPESTATUS[0]}`
 echo $ts

ただし、$tsには何も表示されません。 $ts変数をどのように表示するのですか、それとも変数のコマンドから終了ステータスコードを取得するのですか?

selentry=`ls -l / | sort`

答え1

存在する:

selentry=`ls -l / | sort ; ts=${PIPESTATUS[0]}`

より現代的なものと同じです。

selentry=$(ls -l / | sort ; ts=${PIPESTATUS[0]})

のコードはサブシェル環境で実行されます($(...)シェルの外部の他のシェルプロセスでも実行されます)。したがって、このサブシェルの変数を変更しても親シェルには影響しません。bashksh93

これを行うとき:

var=$(cmd)

ただし、終了ステータスはcmdで利用できます$?。これは$PIPESTATUS次の状況には適用されません。

var=$(foo | bar)

1つの値のみを含めます(ここで終了状態になるサブシェルの終了コードbar(該当するオプションがオンになっていない場合はpipefail0以外の場合は終了状態になる可能性があります)。)配列は次の場所にあります。割り当てコマンドInfluenceの影響を受けません。foozsh$pipestatus

しかし、ここで(サブシェルの)終了状態に興味がない場合は、sort次のようにすることができます。

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に似た他のシェルには同様の機能がないため、他の手段(一時ファイルなど)を介してデータを渡す必要があります。

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]}

関連情報