庆典:得到传递给脚本文字的参数,并执行它们作为命令 [英] bash: get literal parameters passed to a script and execute them as a command
问题描述
我写一个bash脚本(名为 foreach_repo
)应该执行传递的参数作为一个shell命令,例如:
I am writing a bash script (called foreach_repo
) that should execute the passed parameters as a shell command, e.g.:
foreach_repo hg status
要执行的命令汞状态
。 (它在这个仓库的一个复杂的嵌套结构,我有过这样的结构无法控制,但我需要一批经常运行他们)。
should execute the command hg status
. (It does this on a complicated nested structure of repositories, I have no control over this structure, but I need to batch operate on them quite often).
这类型的命令是类似于须藤
及其他高阶命令;例如 sudo的汞状态
将依次执行汞状态
以超级用户权限。
This type of command is similar to sudo
and other 'higher-order' commands; for example sudo hg status
would in turn execute hg status
with superuser rights.
在内部,我的脚本执行以下操作(给出的标准输入资料库路径的饲料,由脚本的另一部分创造的 - 无关的这个问题):
Internally, my script does the following (given a feed of repository paths on stdin, created by another part of the script - irrelevant to this question):
while read repo do
container="$repo/.."
cd $base/$container
$@
done
其中, $ @
意味着国米preT传递的参数作为存储库中要执行的命令。
Where $@
is meant to interpret the passed arguments as the command to be executed in the repository.
本办法正常工作对简单的命令,例如:
This approach works fine for simple commands, for example
foreach_repo hg status
将正确返回结构的每个库的状态列表。然而,更复杂的命令(带逃脱,报价...)都搞砸了。例如,当我尝试
will correctly return the status list of every repository in the structure. However, more complicated commands (with escapes, quotes ...) are messed up. For example, when I try
foreach_repo hg commit -m "some message"
我得到
abort: message: no such file or directory
由于引号被扒掉,实际执行的命令是:
Because the quotes were stripped off, the actual command executed was:
hg commit -m some message
试图解决方案
手动去除引号,或整个命令传递,一直没有效果,无论是已使用 $ *
而不是 $ @
。然而,命令,如须藤
可以处理这种情况,那就是:
Attempted solutions
Manually escaping the quotes, or the entire command to be passed, has no effect, neither has using $*
instead of $@
. However, commands like sudo
can handle this type of situation, that is:
sudo hg commit -m "some message"
实际上(正确)执行
would actually (and correctly) execute
hg commit -m "some message"
我如何可以完成相同的行为?
How can I accomplish the same behavior?
推荐答案
您在正确的轨道上,几乎得到了它。你只需要使用$ @
而不是 $ @
。
You are on the right track, and almost got it. You just need to use "$@"
instead of $@
.
下面是一个总结什么 $ *
和 $ @
做的,不管有没有行情:
Here's a summary of what $*
and $@
do, with and without quotes:
-
$ *
和$ @
粘贴位置参数,然后tokenise他们(使用$ IFS
)为单独的字符串。 -
$ *
膏,用$ IFS
的第一个字符(通常一个空间插入每个之间)。 -
$ @
膏中的位置参数,为每个参数字符串。
在位置参数作为一个字符串
$*
and$@
paste in the positional arguments, then tokenise them (using$IFS
) into separate strings."$*"
pastes in the positional arguments as one string, with the first character of$IFS
(usually a space) inserted between each."$@"
pastes in the positional arguments, as a string for each argument.
例如:
$ set foo bar "foo bar:baz"
$ printf "%s\n" $*
foo
bar
foo
bar:baz
$ printf "%s\n" $@
foo
bar
foo
bar:baz
$ printf "%s\n" "$*"
foo bar foo bar:baz
$ printf "%s\n" "$@"
foo
bar
foo bar:baz
下面是当你设置什么样的变化 $ IFS
:
Here's what changes when you set $IFS
:
$ IFS=:
$ printf "%s\n" $*
foo
bar
foo bar
baz
$ printf "%s\n" $@
foo
bar
foo bar
baz
$ printf "%s\n" "$*"
foo:bar:foo bar:baz
$ printf "%s\n" "$@"
foo
bar
foo bar:baz
这篇关于庆典:得到传递给脚本文字的参数,并执行它们作为命令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!