私はrbenv
(Rubyバージョンマネージャ)をマシンにインストールしており、次のように動作します。
_$ rbenv local
2.3.1
_
Rubyのローカルバージョンをstdoutに書き込みます。このバージョンを救出し、変数で宣言して別の機会で再利用したい。
_$ declare -r Ruby_DEFINED_VERSION=$(rbenv local)
$ echo Using Ruby version $Ruby_DEFINED_VERSION
Using Ruby version 2.3.1
_
できます!
しかし、私は($()
または_``
_を使用して)subshellを使用して作業を行いたくありません。同じShellを使用したいのですが、tmpファイルを作成して作業を行いたくありません。
これを行う方法はありますか?
注: _declare -r
_は必須ではなく、単純な_var=FOOBAR
_でもかまいません。
ハックはありますが、ループで必要な場合にのみ意味があると思います。
次のようにcat
coproc
を開くことができます:coproc CAT { cat; }
これにより、cat
コマンドがバックグラウンドで開始され、2つの環境変数CAT_PID
およびCAT
が設定されます。 CAT
変数は、STDOUT
によって使用されるSTDIN
およびcat
(この順序で)ファイル記述子(パイプ)を含む配列です。
したがって、STDIN
を表す&${CAT[1]}
に出力を書き込むものを実行し、組み込みコマンドread
を使用して、変数である${CAT[0]}
からの変数の読み取りを設定できます。猫のSTDOUT
。
ここにサンプル:
coproc CAT { cat; }
echo 123 >&${CAT[1]}
read myvar <&${CAT[0]}
テストする:
echo $myvar
123
使用後は必ず猫を止めてください。プロセスを強制終了することで実行できます。
kill $CAT_PID
これにより、パフォーマンスチューニングに大きな違いが生まれます。
Bashを使用すると、次のようにすることもできます。
read a < <(echo hello)
echo "$a"
またはこのように:
shopt -s lastpipe
echo hello | read a
shopt -u lastpipe
echo "$a"
しかし、Rubyを実行するサブプロセスを起動する必要があるため、回避しようとしていることがよくわかりません...
Linuxの場合、bash
を使用すると次のことができます。
{
chmod u+w /dev/fd/3 # only needed in bash 5+
rbenv local > /dev/fd/3
IFS= read -rd '' -u 3 variable
} 3<<< ''
それはあなたには隠されていますが、あらゆるhere-documentやhere-stringのような一時ファイルを使用します。
rbenv
が出力するデータがブロックせずにパイプに収まらない場合(通常は64KiB)、LinuxとLinuxでのみ、次のように一時ファイルの代わりにパイプを使用できます。
{
chmod u+w /dev/fd/3 # only needed in bash 5+
rbenv local > /dev/fd/3
IFS= read -rd '' -u 3 variable
} 3< <(:)
ksh93
またはmksh
の最近のバージョンでは、サブシェルを開始しないコマンド置換の形式を使用します。
variable=${
rbenv local
}
IFS= read -rd ''
とは逆に、出力の末尾の改行文字が削除されることに注意してください(すべてのコマンド置換と同様)。