在函数内将多个参数传递给 sudo

在函数内将多个参数传递给 sudo
foo (){
            sudo -- sh -c "cd /home/rob; echo \"$@\""
}

我正在尝试创建一个 bash 函数,.bashrc将 sudo 更改为特定目录,然后运行 ​​Python 命令。出于演示目的,我在上面的示例中将其更改为 echo。

尽管我已引用$@将所有参数传递给 echo 命令,但它仅适用于一个:

$ foo 1
1
$ foo 1 2
2": -c: line 0: unexpected EOF while looking for matching `"'
2": -c: line 1: syntax error: unexpected end of file

是什么赋予了?如何向该函数传递多个参数?

答案1

添加set -v到您的函数中,您将看到发生了什么:

$ f (){ set -v; sudo -- sh -c "cd /tmp; echo \"$@\""; } 
$ f 1 2
+ sudo -- sh -c 'cd /tmp; echo "1' '2"'

怎么了?您的使用$@创建了两个字符串,并用单引号引起来cd /tmp; echo "12"$*如果您不想进行这种拆分,则可以使用。请参阅 bash 手册页部分特殊参数

@ ...当扩展发生在双引号内时,每个参数都会扩展为一个单独的单词。 ... 如果... 在一个单词内,第一个参数的扩展与原始单词的开头部分连接,最后一个参数的扩展与原始单词的最后部分连接。

因此,在您的情况下,单个字符串(或单词)“xxx$@yyy”扩展为 2 个字符串“xxx1”和“2yyy”。您可以使用set -- 1 2 3set 来测试它$@,然后使用printf ">%s<" "$@"来查看变为的单词数"$@"(因为 printf 将为每个参数重复格式):

$ set -- 1 2 3
$ printf ">%s< " "x$@y"
>x1< >2< >3y<
$ printf ">%s< " "x$*y"
>x1 2 3y<

如果您想将参数传递给sh -c command一个 hack,请将它们作为参数放置在单个命令之后,但这可能不适用于所有 shell:

f (){ set -v; sudo -- sh -c 'cd /tmp; echo "$@"' sh "$@"; }
f 1 2
+ sudo -- sh -c 'cd /tmp; echo "$@"' sh 1 2

额外的sh参数是因为第一个参数被 shell 作为进程的名称。

相关内容