パイプの出力を変数に入れようとしています。私は以下を試しました:
echo foo | myvar=$(</dev/stdin)
echo foo | myvar=$(cat)
echo foo | myvar=$(tee)
しかし、$myvar
それは空でした。
私はしたくありません:
myvar=$(echo foo)
サブシェルを作成したくないからです。
どんなアイデアがありますか?
編集する:パイプの前のコマンドを使用するにはグローバル変数を編集する必要がありますが、サブシェルではこれを実行できないため、サブシェルを作成したくありません。できますか?状況はecho
単純化するためのものです。それは次のとおりです。
complex_function | myvar=$(</dev/stdin)
なぜこれがうまくいかないのか分かりません。たとえば、次のようになります。
complex_function | echo $(</dev/stdin)
答え1
正しい回避策は、次のコマンド置換を使用することです。
variable=$(complex_command)
良い
message=$(echo 'hello')
(またはmessage=hello
この場合)。
あなたのパイプライン:
echo 'hello' | message=$(</dev/stdin)
または
echo 'hello' | read message
実際に動作します。唯一の問題は、サブシェルがパイプラインの2番目の部分を実行するシェルを使用していることです。パイプが終了すると、サブシェルが破壊されるため、値は$message
シェルに保持されません。
ここでどのように動作するかを確認できます。
$ echo 'hello' | { read message; echo "$message"; }
hello
...しかし、サブシェルの環境は独立しているので(そして消えます):
$ echo "$message"
(出力なし)
ksh93
1つのソリューションは、よりスマートなソリューションに切り替えることです。
$ echo 'hello' | read message
$ echo "$message"
hello
別の解決策はシェルオプションをbash
設定することです。lastpipe
これにより、パイプラインの最後の部分が現在の環境で実行されます。ただし、lastpipe
ジョブ制御を有効にしてはいけないため、対話型シェルでは機能しません。
#!/bin/bash
shopt -s lastpipe
echo 'hello' | read message
echo "$message"
答え2
コマンド置換の使用:
myvar=`echo foo`
または
myvar=$(echo foo)
答え3
グローバル変数を変更してその内容をstdoutに印刷する関数が与えられた場合:
global_variable=old_value
myfunction() {
global_variable=new_value
echo some output
}
ksh93
mksh R45以降では、次のものを使用できます。
var=${
myfunction
}
それから:
$ print -r -- "$global_variable, $var"
new_value, some output
${ ...; }
サブシェルを生成しないコマンド代替形式。組み込みコマンドの場合、出力をパイプに書き込むのではなく(これを行うには、デッドロックを避けるためにパイプで読み書きする他のプロセスが必要です)、ksh93
何も出力せずに内容を収集してエクスポートしました。拡張のために登場しました。mksh
代わりに一時ファイルを使用してください。
$ ksh -c 'a=${ b=123; echo foo;}; print -r -- "$a $b"'
foo 123
fish
コマンドの代替動作もksh93に似ています${ ...; }
。
$ fish -c 'set a (set b 123; echo foo); echo $a $b'
foo 123
他のほとんどのシェルは一時ファイルを使用します。
myfunction > file
var=$(cat file) # can be optimised to $(<file) with some shells
Linuxでは、bash
4.4以前のバージョンを使用するかzsh
(一時ファイルを使用<<<
)、次のことができます。
{
myfunction > /dev/fd/3 &&
var=$(cat<&3)
} 3<<< ''
では、zsh
次のこともできます。
() {
myfunction > $1
var=$(<$1)
} =(:)
ksh、zsh、bashなどのKorn様シェルでは、$(cmd...)
標準形式またはバリアント$(<file)
のコマンド置換${ cmd...; }
はすべての末尾の改行文字(file
または出力cmd
)を削除します。バラよりシェル: コマンド置換で末尾の改行 ('\n') を保持します。この問題を解決する方法を学びます。
で、出力の各行を配列のfish
個々の要素に割り当てます。出力または 。バージョン 3.4.0 以降、Korn シェルの動作と同様の動作 (末尾の改行をすべて削除) もサポートされます。set var (cmd)
cmd
$var
$var
cmd
foo
foo<newline>
fish
set var "$(cmd)"
答え4
一時ファイルを使用して複雑な関数の結果を保存し、処理のために一時ファイルから値を読み取ります。
# Create a temp file for storage
tmppath=$(mktemp)
# run the command and get the output to the temp file
complex_command > "${tmppath}"
# read the file into variable
message=$(cat "${tmppath}")
# use the variable
echo "$message"
rm -f "${tmppath}"
利用方法mktemp
を参照してくださいシェルスクリプトで一時ファイルを作成するには?