ソース/dev/stdinが期待どおりに機能しません。

ソース/dev/stdinが期待どおりに機能しません。

これが機能していることを確認するために、効果的な簡単なテストから始めましょうsource /dev/stdin

# echo -ne 'echo a\necho b\n' | source /dev/stdin
a
b

さて、実際の機能を手に入れたいです。

# echo -ne 'f() { echo a; }\n' | source /dev/stdin
# f
-bash: f: command not found

それでは、一時ファイルを試してみましょう。

# echo -ne 'f() { echo a; }\n' > tempf
# source tempf
# f
a

これにより一時ファイルが機能します。しかし、私が見るのは非常に不便で、パイプが正しく動作しない妥当な理由は見えません。

# bash --version
GNU bash, version 4.2.53(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

完全性を期すために、実際のユースケースは、Gentoo Portageの制限を解決するために含めるファイルの部分を慎重に選択することです。

post_src_unpack() {
    if type epatch_user > /dev/null 2>&1; then
        epatch_user || die
    else
        awk \
            '/^# @FUNCTION: / { p = 0 } /^# @FUNCTION: epatch(_user)?$/ { p = 1; } p { print  }' \
            /usr/portage/eclass/eutils.eclass | source /dev/stdin || die
        epatch_user || die
        unset epatch
        unset epatch_user
    fi
}

このコードの目的は、多数の関数を含むソースファイルから2つの必須関数を抽出してepatch現在のepatch_userシェルで使用できるようにし、そのうちの1つを実行してから(別のものを使用)削除することです。究極の目標は、継承されたebuildだけがeutilsアクセスできるGentooの制限を解決することですepatch_user

答え1

あなたはそれを使用することができますプロセスの交換

source /dev/stdin < <(echo -ne 'f() { echo a; }\n')

または

source <(echo -ne 'f() { echo a; }\n')

これはbash 4.1.5で動作しますが、何らかの理由で3.2.48では動作しません。

答え2

各部管路飛び込む別々のプロセスまたは独自のサブシェル。したがって、パイプラインが完了すると、現在のシェルは関数について何も知りませんf

bashkshまたはpdkshシェルを使用zshしてmkshサポートここにある文字列)、あなたが使用できる:

$ source /dev/stdin <<<'f() { echo a; }'
$ f
a

POSIXly、あなたは使用する必要がありますここのドキュメントそして指す:

$ . /dev/stdin <<'EOF'
> f() { echo a; }
> EOF

$ f
a

答え3

/dev/stdinパイプラインのコマンドは別々のプロセスなので、パイプラインが完了すると派生した関数定義が失われます。これがパイプが一時ファイルを使用したのとは異なる結果を示す理由です。

あなたのユースケースでは、evalPM 2Ringが提案するアプローチが最善の選択肢となります。

関連情報