私のコンピュータに(Ruby Version Manager)をインストールしましたが、rbenv
次のように動作します。
$ rbenv local
2.3.1
に書く標準出力私のローカルバージョンのRubyです。このバージョンを救出し、他の場合に再利用できるように変数に宣言したいと思います。
$ declare -r RUBY_DEFINED_VERSION=$(rbenv local)
$ echo Using ruby version $RUBY_DEFINED_VERSION
Using ruby version 2.3.1
効果がある!
しかし、使用したくないサブシェル作業を完了します($()
または使用``
)。私も同じように使いたいシェル私tmp操作を完了するために必要なファイルです。
これを行う方法はありますか?
メモ: declare -r
必須ではなく、簡単にすることができますvar=FOOBAR
。
答え1
ハッキングがありますが、ループを介して実行する必要がある場合は意味があると思います。
次のように開くことができますcat
coproc
。coproc CAT { cat; }
これにより、cat
バックグラウンドでコマンドが実行され、2つの環境変数(CAT_PID
および)が設定されますCAT
。この変数は、使用されるファイル記述子(パイプ)を(順番に)含むCAT
配列です。STDOUT
STDIN
cat
&${CAT[1]}
したがって、表示されるすべての項目に出力を書き込むことができ、STDIN
組み込みコマンドを使用してread
読み取る変数をcatに設定${CAT[0]}
できますSTDOUT
。
例は次のとおりです。
coproc CAT { cat; }
echo 123 >&${CAT[1]}
read myvar <&${CAT[0]}
テストするには:
echo $myvar
123
使用後は猫をブロックすることを忘れないでください。プロセスを終了したらこれを行うことができます。
kill $CAT_PID
これはパフォーマンスチューニングに大きな影響を与えます。
更新:区切り文字列をbash
実装しましたnull
。だからバイナリデータを扱うときはread
本当に面倒です。一度に1バイトずつ読み取ることができ、nullは変数の空の文字列にLC_ALL=C read -r -n1 -d $'\0'
なります。${REPLY}
答え2
Bashを使用すると、次のこともできます。
read a < <(echo hello)
echo "$a"
または次のようになります。
shopt -s lastpipe
echo hello | read a
shopt -u lastpipe
echo "$a"
しかし、まだRubyを実行するサブプロセスを開始する必要があるので、何を避けたいのかわかりません...
答え3
Linuxでbash
5.1(またはzsh)以前のバージョンを使用している場合は、次のことができます。
{
chmod u+w /dev/fd/3 # only needed in bash 5.0
rbenv local > /dev/fd/3
IFS= read -rd '' -u 3 variable
} 3<<< ''
非表示ですが、ここではドキュメントごと、またはここでは文字列などの一時ファイルを使用します。
bash
5.1通常の一時ファイルの代わりにパイプを使用します(少なくともherefile / herestringの内容がパイプバッファに入るのに十分小さい場合)。これにより、いつでも一時ファイルを手動で作成できます。
tmpfile=$(mktemp) || exit
{
rm -f -- "$tmpfile"
rbenv local >&3
IFS= read -rd '' -u4 variable
} 3> "$tmpfile" 4< "$tmpfile"
<<
<<<
(たとえば、シェルがシャットダウンしたときにスクリプトがシャットダウンまたは残されるリスクを最小限に抑えるために、tmpfileを早期に削除してください)。rbenv
出力がパイプに入ることができるよりも少ないデータ(通常64KiB)の場合は、rbenv
まだLinuxとLinuxでのみ一時ファイルの代わりにパイプを使用できます。
{
rbenv local > /dev/fd/3
IFS= read -rd '' -u 3 variable
} 3< <(:)
ksh93
または、最新バージョンの場合は、mksh
サブシェルを起動しないコマンド代替形式を使用してください。
variable=${
rbenv local
}
このバージョンは、現在のbashおよびzsh開発バージョンでも利用できます。
この方法とは異なり、IFS= read -rd ''
出力から末尾の改行を削除します(通常のコマンド置換と同様)。
これを達成するために、ksh93の現在のバージョン(2024年)は、内部的に事前に削除された一時ファイル(/dev/shm
私のDebianシステム上)、mksh(/tmp
私のシステム上)、zsh-devを使用し、ファイルのみが後で削除されます。 bash-devを削除して匿名にするメモリサポートされている場所には一時ファイルがあり、サポートされていない場所には事前に削除された一時ファイルがあります/tmp
。
以前のバージョンでは、自動的に削除された一時ファイルをインポートするためにプロセス置換形式をzsh
利用しました(ここでは匿名関数のパラメータとして渡されました)。=(...)
() { rbenv local > $1; IFS= read -rd '' variable <$1; } =()
1 しかし、zshに関する限り、${ cmd }
現在これを行うか引用符なしで実行するかについての議論があります。