Fish 쉘의 $argv는 bash의 $@와 다릅니까?

Fish 쉘의 $argv는 bash의 $@와 다릅니까?

일부 물고기 스크립트를 배우고 작성하려고 하는데 이상한 문제에 봉착했습니다.

# 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가 변수를 다르게 처리하는지 물어봐야 할까요?)

나는 이것이 단순한 교체라고 생각했지만 이것이 나를 혼란스럽게 합니다. 누구든지 나를 도와줄 수 있나요? 어떤 도움이라도 대단히 감사하겠습니다 :)

운영 체제: 우분투 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)단일 문자열이 아닌 항목 목록을 기대하기 때문에 실패합니다.

on은 를 표시 strace해야 합니다 . 한 가지 가정은 요소를 개별 항목으로 혼합하는 대신 목록으로 분할한다는 것입니다.bash"$@"

관련 정보