我试图学习和编写一些鱼脚本,但遇到了一个奇怪的问题。
# a.fish
# this is a fish script
set temp (getopt -o abc -l ace,bad,correct -- $argv)
echo $temp
当我运行时fish ./a.fish -a -b --correct
它工作正常并输出
-a -b --correct --
但是,当我更改$argv
为"$argv"
并再次运行时,我得到了这个
然后我写了一个bash脚本
# a.sh
temp=$(getopt -o abc -l ace,bad,correct -- $@)
echo $temp
并用 运行它bash ./a.sh -a -b --correct
。工作得很好。我添加后"
它$@
仍然工作得很好!
那么问题来了:
$argv
和之间有什么区别$@
(或者也许我应该问 Fish 和 bash 处理变量是否不同?)
我以为这只是简单的替换,但这让我很困惑。有人可以帮助我吗?任何帮助将不胜感激 :)
操作系统:ubuntu 16.04
答案1
是的,不同的外壳是不同的。strace
一如既往,可以帮助显示通过execve(2)
呼叫发送的具体内容。
$ cat fecho
/usr/bin/echo $argv
$ cat fechoquoted
/usr/bin/echo "$argv"
$ fish ./fecho a b c
a b c
$ fish ./fechoquoted a b c
a b c
$
然而,这两者实际上在 -scope 下有很大不同strace
:
$ strace -qq -f -e trace=execve fish ./fecho a b c
execve("/usr/bin/fish", ["fish", "./fecho", "a", "b", "c"], [/* 22 vars */]) = 0
[pid 15532] execve("/usr/bin/echo", ["/usr/bin/echo", "a", "b", "c"], [/* 21 vars */]) = 0
a b c
$ strace -qq -f -e trace=execve fish ./fechoquoted a b c
execve("/usr/bin/fish", ["fish", "./fechoquoted", "a", "b", "c"], [/* 22 vars */]) = 0
[pid 15542] execve("/usr/bin/echo", ["/usr/bin/echo", "a b c"], [/* 21 vars */]) = 0
a b c
$
第一个将参数列表传递给echo
(“a”,“b”,“c”),第二个传递单个列表项(“ab c”)。因此,在您的getopt
情况下,当引用为“$argv”时,参数将getopt(1)
作为单个字符串传递,而不是作为单个元素的列表传递,并且getopt(1)
会失败,因为它需要一个项目列表,而不是单个字符串。
onstrace
应该bash
显示什么"$@"
;一个假设是它将元素拆分到一个列表中,而不是将它们作为单个项目混合在一起。