让我们从对我有用的简单测试开始,以检查是否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
}
该代码的目的是从包含大量函数的源文件中提取两个所需的函数epatch
,epatch_user
使它们在当前 shell 中可用,运行其中一个(反过来使用另一个),然后删除它们。最终目标是解决 Gentoo 的限制,即只有继承的 ebuildeutils
才能访问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
各部分管道跑进独立的进程,或自己的子shell。因此,当您的管道完成时,您当前的 shell 对 function 一无所知f
。
使用bash
( ksh
、pdksh
、zsh
或mksh
shell 来支持这里的字符串),你可以使用:
$ source /dev/stdin <<<'f() { echo a; }'
$ f
a
$ . /dev/stdin <<'EOF'
> f() { echo a; }
> EOF
$ f
a
答案3
/dev/stdin
管道中的命令是单独的进程,因此一旦管道完成,源自的函数定义就会丢失。这就是为什么管道显示与临时文件的使用不同的结果。
在您的用例中,eval
PM 2Ring 建议的方法将是最佳选择。