Bash 函数调用作为参数给出的命令
如何在 bash 中编写一个函数来执行作为参数给出的命令,其中
- 给定的命令可能是别名
- 参数必须完全按照给定的方式传递;可以不进行评估
换句话说,如何编写尽可能透明的包装器函数。
例如,包装函数的目标可以是在给定命令之前和之后设置当前目录,和/或设置环境变量,或者计算给定命令需要多长时间,...作为一个简单的例子,我在这里采用一个函数它只打印一行,然后执行给定的命令。
第一次尝试:
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一样直接传递参数?
How do you write a function in bash that executes the command that it is given as an argument, where
- The given command may be an alias
- Arguments must be passed on exactly as given; no evaluating may be done
In other words, how to write an as-transparent-as-possible wrapper function.
The goal of the wrapper function could for example be to set the current directory before and after the given command, and/or set environment variables, or time how long the given command takes,... As a simple example here I take a function that just prints a line and then executes the given command.
A first attempt:
function wrap1 {
echo Starting: "$@"
"$@"
}
You could use it like wrap1 echo hello
. But the problem is you cannot do alias myalias echo
and then call wrap1 myalias hello
: it wouldn't resolve the alias.
Another attempt using eval
:
function wrap2 {
echo Starting: "$@"
eval "$@"
}
Now calling an alias works. But the problem is it evaluates the arguments too. For example wrap2 echo "\\a"
prints just a
instead of \a
because the arguments are evaluated twice.
shopt -s expand_aliases
doesn't seem to help here either.
Is there a way to both evaluate aliases like wrap2, but still pass on the arguments directly like wrap1?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您(呃,我)可以使用 printf %q 来转义参数。
乍一看,用 printf 转义然后执行 eval 总是给出与直接传递参数相同的结果。
You (uh, I) can use printf %q to escape the arguments.
At first sight, escaping with printf and then doing eval always gives the same result as passing the arguments directly.
似乎可以使用双
eval
:所以也许你的函数可以写成如下:
但是,
eval
是邪恶的,双eval
这是双重邪恶的,并且由于某种原因,别名不会在脚本中扩展。It seems to be possible with a double
eval
:So maybe your function could be written as follows:
However,
eval
is evil, and doubleeval
is double evil, and aliases are not expanded in scripts for a reason.