我想在bash脚本中创建一个函数,声明一个变量和值提供给稍后要重用的函数。
function format_msg {
declare "$1"="[ \033[00;32m$2 OK\033[0m ]"
}
format_msg "foo" "bar"
echo "${!foo}"
这是一个返回空值
答案 0 :(得分:3)
declare
builtin声明 local 变量(使用动态范围);所以当函数返回时变量就会消失。
如果你有一个足够新版的Bash,一个选项就是使用printf
-v var
选项(保存到变量而不是写入标准输出):
function format_msg {
printf -v "$1" "%s" "[ \033[00;32m$2 OK\033[0m ]"
}
(也就是说,我同意CMPS的建议,你只需更改你的功能,使仅处理格式化,并让调用代码处理分配。一般的想法在Unix编程中,做一件事并做得很好"。)
编辑添加:我还应该指出代码中的其他两个问题,一旦解决上述问题就会遇到问题:
除非您echo
是专门定义的(例如,您已启用对反斜杠转义的支持),否则您似乎无法处理{{1}以便获得实际的颜色格式。所以我想你可能真的想要
\033
printf -v "$1" "[ \033[00;32m%s OK\033[0m ]" "$2"
处理printf
。
\033
会将"${!foo}"
的内容解释为新的变量名,然后展开 的结果变量;我很确定你只想要
$foo
答案 1 :(得分:1)
使用函数内部的声明使其成为函数的本地函数。
请改为尝试:
function format_msg {
echo "[ \033[00;32m$1 OK\033[0m ]"
}
foo=$(format_msg "bar")
echo $foo
答案 2 :(得分:1)
declare
会创建一个局部变量。从bash
4.2开始,您可以使用-g
选项来创建全局变量。
function format_msg {
declare -g "$1=[ \033[00;32m$2 OK\033[0m ]"
}
答案 3 :(得分:0)
正如已经说过的那样,在这种特定情况下你的代码失败了,因为当使用declare时,bash会生成一个变量(好像命令一样)local
(已经发出)。这相当于ksh的typeset
,以及zsh的typeset
,以及其替代形式declare
,integer
,local
和readonly
(但不是export
)。
此外,您正尝试通过间接形式echo "${!foo}"
进行打印。这不会打印$foo
的值,而是打印变量的值(如果存在),其名称是$foo
的值。
如果使用此表单,则可以在函数内使用declare(对于bash 4.2 +):
declare -g "$1"="[ \033[00;32m$2 OK\033[0m ]"
对于较旧的bash版本(通常对于大多数shell)而不使用declare
进行分配的最基本方法是始终令人担忧的eval(如果$1
或{{1}的值有任何机会被攻击者(或外部用户)设置):
$2
当然,这会将字符串eval "$1"='"[ \033[00;32m'"$2"' OK\033[0m ]"'
分配给[ \033[00;32mbar OK\033[0m ]
,这似乎不是预期的目标。
这个简单的更改应该正确地将预期的转义字符分配给变量:
$foo
eval "$1"=$'"[ \033[00;32m'"$2"$' OK\033[0m ]"'
将更改为绿色,然后重置颜色设置。
为了消除评估的风险,我们需要使用其他东西。
对于ksh 93+和bash 4.3+,我们可以使用bar OK
s(使用bash格式):
nameref
或者bash printf的-v选项:
declare -n ref=$1
ref=$'"[ \033[00;32m'"$2"$' OK\033[0m ]"'
在这种情况下,转义码(printf -v "$1" '"[ \033[00;32m%s OK\033[0m ]"' "$2"
)的解释由printf完成。
一旦变量包含所需的值,最好使用printf打印而不是echo,并且不需要间接:
\033