我有以下功能。
hello () {
echo "Hello"
}
func () {
hello
echo "world"
}
如果我不希望打印hello函数的输出但想要对它做一些事情,我想在某个变量中捕获输出,唯一可能的方法是分叉子shell,如下所示?这不是一个不必要的新子进程创建吗?这可以优化吗?
func () {
local Var=$(hello)
echo "${Var/e/E} world"
}
答案 0 :(得分:3)
您可以使调用者传递变量名来保存输出值,然后在函数内创建一个具有该名称的全局变量,如下所示:
myfunc() { declare -g $1="hello"; }
然后将其称为:
myfunc mystring
echo "$mystring world" # gives "hello world"
因此,您的功能可以重写为:
hello() {
declare -g $1="Hello"
}
func() {
hello Var
echo "${Var/e/E} world"
}
唯一的限制是用于保存输出值的变量不能是本地的。
关于使用namerefs的相关文章:
答案 1 :(得分:2)
一个丑陋的解决方案是暂时替换echo
,以便设置一个全局变量,您可以从函数中访问该变量:
func () {
echo () {
result="$@"
}
result=
hello
unset -f echo
echo "Result is $result"
}
我同意这是令人讨厌的,但避免使用子贝壳。
答案 2 :(得分:2)
如何使用文件描述符和Bash here字符串?
hello () {
exec 3<<<"Hello"
}
func () {
local Var
exec 3>&-
hello && read Var <&3
echo "${Var/e/E} world"
exec 3>&-
}
func
答案 3 :(得分:2)
不是bash的答案:至少有一个shell, ksh 优化命令替换[trace] ?- isTaughtBy(jack,doe).
Call: (8) isTaughtBy(jack, doe) ? creep
Call: (9) teaches(doe, _18526) ? creep
Exit: (9) teaches(doe, cs01) ? creep
Call: (9) student(jack, _18526, _18528, _18530) ? creep
Exit: (9) student(jack, 100, 21, m) ? creep
Call: (9) takes(100, cs01) ? creep
Exit: (9) takes(100, cs01) ? creep
Exit: (8) isTaughtBy(jack, doe) ? creep
true ;
Redo: (9) takes(100, cs01) ? creep
Fail: (9) takes(100, cs01) ? creep
Fail: (8) isTaughtBy(jack, doe) ? creep
false.
到而不是为内置命令生成子shell。当您的脚本倾向于执行大量这些操作时,这非常有用。
答案 4 :(得分:1)
您可以选择修改hello()
函数吗?如果是这样,那么给它一个选项,将结果存储在变量中:
#!/bin/bash
hello() {
local text="hello"
if [ ${#1} -ne 0 ]; then
eval "${1}='${text}'"
else
echo "${text}"
fi
}
func () {
local var # Scope extends to called functions.
hello var
echo "${var} world"
}
还有更紧凑的hello()
版本:
hello() {
local text="hello"
[ ${#1} -ne 0 ] && eval "${1}='${text}'" || echo "${text}"
}
答案 5 :(得分:0)
这并不能从字面上回答这个问题,但是对于某些用例,这是一种可行的替代方法...
这是@Andrew Vickers的衍生产品,您可以依靠eval
。
而不是定义一个函数,而是定义一个我称之为“宏”(C语言等效项)的东西:
MACRO="local \$var=\"\$val world\""
func()
{
local var="result"; local val="hello"; eval $MACRO;
echo $result;
}