web-dev-qa-db-ja.com

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

出力を生成するbash関数があります。

function scan {
  echo "output"
}

この出力を変数に割り当てるにはどうすればよいですか?

すなわち。 VAR = scan(もちろんこれは機能しません-VARを文字列 "scan"と等しくします)

74
Brent
VAR=$(scan)

プログラムとまったく同じ方法。

114
Robert Obryk

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

===

この形式にはいくつかの利点があります。つまり、関数はどこでもグローバル変数を使用せずに呼び出し元の環境を変更できます。

注:関数がbashビルトインに大きく依存している場合、namerefsを使用すると、すぐに捨てられるサブシェルの作成が回避されるため、プログラムのパフォーマンスが大幅に向上します。これは一般的に、頻繁に再利用される小さな機能、例えばecho "$returnstring"で終わる関数

これは関連しています。 https://stackoverflow.com/a/38997681/5556676

15
init_js

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
}
0