web-dev-qa-db-ja.com

bash関数はどのようにして複数の値を返すことができますか?

Bash関数からの戻り値many値のベストプラクティスは何ですか?

例1:

関数スクリプト:

function mysqlquery {
    local dbserver='localhost'
    local dbuser='user'
    local dbpass='pass'
    local db='mydb'
    mysql -h "$dbserver" -u "$dbuser" -p "$dbpass" --skip-column-names --raw -e "$*" "$db"
    if [ $? -ne 0 ]; then
        return 1
    fi
}

ソーススクリプト:

for XY in $(mysqlquery "select XY from ABC where DEF = 123" 2>/dev/null);do
    dosomethingwith $XY
done
if mysqlquery "select XY from ABC where DEF = 123" 2>/dev/null; then
    echo true
fi

例2:

関数スクリプト:

function mysqlquery {
    local dbserver='localhost'
    local dbuser='user'
    local dbpass='pass'
    local db='mydb'
    result=$(mysql -h "$dbserver" -u "$dbuser" -p "$dbpass" -e "$*" "$db" 2>/dev/null)
    if [ $? -ne 0 -o -z "$result" ]; then
        return 1
    fi
}

ソーススクリプト:

result=$(mysqlquery "select XY from ABC where DEF = 123" 2>/dev/null)
for XY in $result;do
    dosomethingwith $XY
done
if mysqlquery "select XY from ABC where DEF = 123" 2>/dev/null; then
    echo true
fi

または、複数の情報を返すためのアプローチは他にもありますか(単一のint値をはるかに超える)?

9
FaxMax

まあ、それはあなたが望む/必要とする出力フォーマットの種類に依存します。最も簡単な方法は、おそらく関数からの出力を出力することです。このようにして、関数は他のコマンドと同じように動作します。別の方法は、関数内から変数(おそらく連想配列)を設定することです。これには、さまざまな項目が明確に分離されるという利点がありますが、一部の変数をハードコーディングする必要がある場合があります。

最初の例の関数は前者を実装します。mysqlクライアントが関数から出力するものはすべて、関数の標準出力に送られます。データがすでにバイトのストリームとして提供されていることを考えると、そのままにしておくのは問題ありません。

ここでは、問題は出力をどうするかになります。 for x in $(somecmd) ...は、somecmdの出力が単語に分割され、ファイル名グロブとして処理されるため、適切ではありません。通常、while read ...を使用することをお勧めします。参照 ファイル(データストリーム、変数)を行ごと(またはフィールドごと)に読み取るにはどうすればよいですか?

mysqlの出力を1行ずつ読み取るには、次のようにします。

mysql -h "$dbserver" etc. etc. | while read -r line ; do
    dosomethingwith "$line"
done

または機能付き

mysqlquery() {
    ...
    mysql -h "$dbserver" etc. etc. 2>/dev/null
}
mysqlquery | while read -r line ; do ...

if [ $? -ne 0 ]; then return 1は必要ないことに注意してください。関数からの戻り値は、前のコマンドの戻り値と同じです。関数を使用してパイプにフィードしている場合、戻り値を調べるのは簡単ではありません。

1
ilkkachu