gpt4 book ai didi

bash:获取传递给脚本的文字参数并将它们作为命令执行

转载 作者:行者123 更新时间:2023-11-29 09:20:34 25 4
gpt4 key购买 nike

目标和背景

我正在编写一个 bash 脚本(称为 foreach_repo),它应该将传递的参数作为 shell 命令执行,例如:

 foreach_repo hg status

应该执行命令hg status。 (它在复杂的存储库嵌套结构上执行此操作,我无法控制这种结构,但我需要经常对它们进行批处理)。

这种类型的命令类似于 sudo 和其他“高阶”命令;例如 sudo hg status 将依次以 super 用户权限执行 hg status

在内部,我的脚本执行以下操作(给定标准输入上的存储库路径提要,由脚本的另一部分创建 - 与此问题无关):

while read repo do
container="$repo/.."
cd $base/$container
$@
done

其中 $@ 用于将传递的参数解释为要在存储库中执行的命令。

执行

这种方法适用于简单的命令,例如

foreach_repo hg status

将正确返回结构中每个存储库的状态列表。然而,更复杂的命令(带有转义符、引号……)被搞砸了。例如,当我尝试

foreach_repo hg commit -m "some message"

我明白了

abort: message: no such file or directory

因为引号被去掉了,实际执行的命令是:

hg commit -m some message

尝试过的解决方案

手动转义引号或要传递的整个命令没有效果,使用 $* 代替 $@ 也没有效果。但是,sudo 这样的命令可以处理这种情况,即:

sudo hg commit -m "some message"

会实际(并且正确地)执行

hg commit -m "some message"

我怎样才能完成相同的行为?

最佳答案

您走在正确的轨道上,并且几乎做到了。您只需要使用 "$@" 而不是 $@

下面是 $*$@ 的作用总结,带引号和不带引号:

  • $*$@ 粘贴位置参数,然后将它们标记化(使用 $IFS)为单独的字符串。
  • "$*" 将位置参数作为一个字符串粘贴,并在每个字符串之间插入 $IFS 的第一个字符(通常是空格)。
  • "$@" 粘贴位置参数,作为每个参数的字符串。

例子:

$ 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 时发生的变化:

$ 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

关于bash:获取传递给脚本的文字参数并将它们作为命令执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18333070/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com