如何在bash中编写一个函数来执行作为参数给出的命令,其中
换句话说,如何编写as-transparent-as-possible wrapper 函数。
包装函数的目标可以是例如在给定命令之前和之后设置当前目录,和/或设置环境变量,或者给定命令花费的时间,...这里的一个简单示例我获取一个只打印一行的函数,然后执行给定的命令。
第一次尝试:
function wrap1 {
echo Starting: "$@"
"$@"
}
您可以像wrap1 echo hello
一样使用它。但问题是您无法执行alias myalias echo
然后调用wrap1 myalias hello
:它无法解析别名。
使用eval
的另一次尝试:
function wrap2 {
echo Starting: "$@"
eval "$@"
}
现在调用别名有效。但问题是它也会对参数进行评估。例如,wrap2 echo "\\a"
只打印a
而不是\a
,因为参数会被评估两次。
shopt -s expand_aliases
似乎也没有帮助。
有没有办法同时评估像wrap2这样的别名,但是仍然像wrap1那样直接传递参数?
答案 0 :(得分:7)
你(呃,我)可以使用printf%q来转义参数。 乍一看,使用printf转义然后执行eval总是会产生与直接传递参数相同的结果。
wrap() {
echo Starting: "$@"
eval $(printf "%q " "$@")
}
答案 1 :(得分:0)
似乎可以使用双eval
:
eval "eval x=($(alias y | cut -s -d '=' -f 2))"
# now the array x contains the split expansion of alias y
"${x[@]}" "${other_args[@]}"
所以也许你的功能可以编写如下:
wrap() {
eval "eval prefix=($(alias $1 | cut -s -d '=' -f 2))"
shift
"${prefix[@]}" "$@"
}
然而,eval
是邪恶的,双eval
是双重邪恶,并且由于某种原因,别名不会在脚本中扩展。