0

関数がどのように値を返すかをテストするために書いたシェル スクリプトで、奇妙な予期しない動作に遭遇しました。以下のコードは、関数 fnttmpfile に入ると、最初の echo ステートメントがコンソールに出力され、次に 2 番目の echo ステートメントが呼び出し元のメインに実際に文字列を返すことを前提としています。と思ったのですが、それは間違いでした!

#!/bin/sh

fntmpfile() {
TMPFILE=/tmp/$1.$$
echo "This is my temp file dude!"
echo "$TMPFILE"
}

mainname=main
retval=$(fntmpfile "$mainname")
echo "main retval=$retval"

実際に起こることは逆です。最初のエコーは呼び出し元の関数に送られ、2 番目のエコーは STDOUT に送られます。これはなぜですか?もっと良い方法はありますか....

main retval=これは私の一時ファイルです! /tmp/main.19121

このテストの全体的な理由は、いくつかのデータベース バックアップを実行するシェル スクリプトを作成していて、特定のことを実行するために小さな関数を使用することにしたためです。私が使用していた機能の1つはこれでした:

log_to_console() {
    # arg1 = calling function name
    # arg2 = message to log
    printf "$1 - $2\n"
}

これに関する全体的な問題は、文字列値を返していた関数が、順序に応じて代わりに log_to_console 出力を取得していることです。これは、私が気付いていなかったシェル スクリプトに関する落とし穴の 1 つだと思います。

4

1 に答える 1

0

いいえ、何が起こっているかというと、関数を実行していて、標準出力に 2 行が出力されているということです。

This is my temp file dude!
/tmp/main.4059

実行すると$()、bash は出力をインターセプトし、値に格納します。変数に格納される文字列には、最初の改行が含まれます (最後の改行は削除されます)。したがって、「retval」変数に実際にあるのは、次の C スタイルの文字列です。

"This is my temp file dude!\n/tmp/main.4059"

これは実際には文字列を返すのではなく (シェル スクリプトでは実行できません)、関数が返す出力をキャプチャしているだけです。それがうまくいかない理由です。コンソールにログを記録する場合は、通常どおり関数を呼び出します。

于 2013-02-12T16:41:33.827 に答える