いくつかの出力を生成するbash関数があります:
function scan {
echo "output"
}
この出力を変数に割り当てるにはどうすればよいですか?
すなわち。VAR = scan(もちろん、これは機能しません-VARを文字列「scan」と等しくします)
回答:
VAR=$(scan)
プログラムの場合とまったく同じ方法です。
通常のプログラムを使用する場合と同じように、コマンド/パイプラインでbash関数を使用できます。これらの関数は、サブシェルおよび推移的にコマンド置換でも使用できます。
VAR=$(scan)
ほとんどの場合、必要な結果を達成するための簡単な方法です。以下に特殊なケースの概要を説明します。
末尾の改行の保持:
コマンド置換の(通常は役立つ)副作用の1つは、後続の改行をいくつでも削除することです。末尾の改行を保持したい場合は、サブシェルの出力にダミー文字を追加し、その後、パラメーター展開を使用してそれを取り除くことができます。
function scan2 () {
local nl=$'\x0a'; # that's just \n
echo "output${nl}${nl}" # 2 in the string + 1 by echo
}
# append a character to the total output.
# and strip it with %% parameter expansion.
VAR=$(scan2; echo "x"); VAR="${VAR%%x}"
echo "${VAR}---"
プリント(3つの改行が保持されます):
output
---
出力パラメーターを使用します:サブシェルを回避します(そして改行を保持します)
関数が達成しようとしているのが、bash v4.3以降で文字列を変数に「返す」ことである場合、と呼ばれるものを使用できますnameref
。Namerefsを使用すると、関数は1つ以上の変数出力パラメーターの名前を取得できます。nameref変数に物事を割り当てることができ、それが指す変数/参照する変数を変更したかのようになります。
function scan3() {
local -n outvar=$1 # -n makes it a nameref.
local nl=$'\x0a'
outvar="output${nl}${nl}" # two total. quotes preserve newlines
}
VAR="some prior value which will get overwritten"
# you pass the name of the variable. VAR will be modified.
scan3 VAR
# newlines are also preserved.
echo "${VAR}==="
プリント:
output
===
このフォームにはいくつかの利点があります。つまり、どこでもグローバル変数を使用せずに、関数が呼び出し元の環境を変更できるようにします。
注:namerefsを使用すると、関数がbashビルトインに大きく依存している場合にプログラムのパフォーマンスを大幅に向上させることができます。これは、直後に破棄されるサブシェルの作成を回避するためです。これは一般に、頻繁に再利用される小さな関数、たとえばecho "$returnstring"
これは関係があります。https://stackoverflow.com/a/38997681/5556676
init_jsはローカルではなく宣言を使用する必要があると思います!
function scan3() {
declare -n outvar=$1 # -n makes it a nameref.
local nl=$'\x0a'
outvar="output${nl}${nl}" # two total. quotes preserve newlines
}
local
ビルトインは、ビルトインが受け入れるすべてのオプションをdeclare
受け入れます。クイックテストからdeclare -n
は、関数スコープ内でも変数ローカルスコープが与えられているように見えます。ここでは互換性があるようです。