bashを使用して関数の出力を変数に割り当てるにはどうすればよいですか?


回答:


144
VAR=$(scan)

プログラムの場合とまったく同じ方法です。


3
「echo $ VAR」を実行したときに、改行が削除されていることを発見しました。代わりに$ VARを引用すると、改行が保持されます。
ブレント

2
それは100%正しくありません。コマンド置換は常に末尾の改行を削除します。
TheBonsai 2009年

7
これにより、サブシェルが作成されます。同じシェルでそれを行う方法はありますか?
限定的贖罪

24

通常のプログラムを使用する場合と同じように、コマンド/パイプラインで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


0

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は、関数スコープ内でも変数ローカルスコープが与えられているように見えます。ここでは互換性があるようです。
init_js 2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.