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 "1
和2"
。$*
如果您不想进行这种拆分,则可以使用。请参阅 bash 手册页部分特殊参数:
@ ...当扩展发生在双引号内时,每个参数都会扩展为一个单独的单词。 ... 如果... 在一个单词内,第一个参数的扩展与原始单词的开头部分连接,最后一个参数的扩展与原始单词的最后部分连接。
因此,在您的情况下,单个字符串(或单词)“xxx$@yyy”扩展为 2 个字符串“xxx1”和“2yyy”。您可以使用set -- 1 2 3
set 来测试它$@
,然后使用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 作为进程的名称。