다른 스크립트를 호출하는 매우 간단한 스크립트를 작성 중이며 현재 스크립트에서 실행중인 스크립트로 매개 변수를 전파해야합니다.
예를 들어, 내 스크립트 이름은 foo.sh
및 전화bar.sh
foo.sh :
bar $1 $2 $3 $4
각 매개 변수를 명시 적으로 지정하지 않고 어떻게해야합니까?
다른 스크립트를 호출하는 매우 간단한 스크립트를 작성 중이며 현재 스크립트에서 실행중인 스크립트로 매개 변수를 전파해야합니다.
예를 들어, 내 스크립트 이름은 foo.sh
및 전화bar.sh
foo.sh :
bar $1 $2 $3 $4
각 매개 변수를 명시 적으로 지정하지 않고 어떻게해야합니까?
답변:
실제로 매개 변수가 동일하게 전달되도록하려면 "$@"
일반 대신 사용하십시오 $@
.
관찰 :
$ cat foo.sh
#!/bin/bash
baz.sh $@
$ cat bar.sh
#!/bin/bash
baz.sh "$@"
$ cat baz.sh
#!/bin/bash
echo Received: $1
echo Received: $2
echo Received: $3
echo Received: $4
$ ./foo.sh first second
Received: first
Received: second
Received:
Received:
$ ./foo.sh "one quoted arg"
Received: one
Received: quoted
Received: arg
Received:
$ ./bar.sh first second
Received: first
Received: second
Received:
Received:
$ ./bar.sh "one quoted arg"
Received: one quoted arg
Received:
Received:
Received:
'arg with spaces'
세 가지 예제에 대한를 포함하면 어떤 일이 발생하는지 보여줄 것을 제안합니다 . 나는 결과에 놀랐다. 잘하면 당신은 그들을 설명 할 수 있습니다.
./foo.sh "arg with spaces"
그리고 ./foo.sh 'arg with spaces'
내가 주어진 예제에 추가의 제안이 어떤 도움이 될 것이라고 표시되지 않습니다, 그래서 100 % 동일하다.
들어 bash는 다른 본쉘 :
java com.myserver.Program "$@"
$argv:q
일부 csh 변형에서 작동 할 것이라고 생각 합니다.
exec java com.myserver.Program "$@"
이렇게하면 bash가 완료 될 때까지 기다리지 않고 java로 실행됩니다. 따라서 하나의 적은 프로세스 슬롯을 사용하고 있습니다. 또한 부모 프로세스 (스크립트를 실행 한)가 pid를 통해 그것을보고 'java'프로세스를 기대하는 경우, exec를 수행하지 않으면 비정상적인 일이 중단 될 수 있습니다. exec는 java가 동일한 pid를 상속하게합니다.
args=("$@")
별도의 쉘 "단어"로 각 요소를 확장 ( 와 (과 "$@"
) 유사합니다 "${args[@]}"
.
"$@"
인수에서 공백을 이스케이프하거나 널 (null) 문자 또는 기타 특수 문자를 이스케이프하면 실패하는 것과 같이를 사용할 때 명심해야 할 "gotchas"가 있습니까?
사용하십시오 "$@"
(모든 POSIX 호환 가능).
[...] bash는 "$ @"변수를 특징으로하며, 공백으로 구분 된 모든 명령 행 매개 변수로 확장됩니다.
에서 배쉬 예에 의해 .
$*
. 나는 여기에 역사적 진보가 있다고 믿는다. $*
설계된대로 작동하지 않았으므로 $@
이를 대체하기 위해 발명되었습니다. 그러나 인용 규칙은 그것이 무엇인지, 그 주위의 큰 따옴표는 여전히 필요합니다 (또는 깨진 $*
의미론으로 되돌아갑니다 ).
echo "$@"
로서 ./script.sh a "b c" d
당신은 얻을 a b c d
대신에 a "b c" d
매우 큰 차이이다.
echo
세 개의 인수를받습니다 "a" "b c" "d"
. 그러나 당신이 사용했다면 당신 for i in "$@"; do echo $i; done
은 얻을 a⏎b c⏎d
것이다.
나는 이것이 잘 대답되었다는 것을 알고 있지만 여기에 "$ @"$ @ "$ *"와 $ *의 비교가 있습니다.
테스트 스크립트의 내용 :
# cat ./test.sh
#!/usr/bin/env bash
echo "================================="
echo "Quoted DOLLAR-AT"
for ARG in "$@"; do
echo $ARG
done
echo "================================="
echo "NOT Quoted DOLLAR-AT"
for ARG in $@; do
echo $ARG
done
echo "================================="
echo "Quoted DOLLAR-STAR"
for ARG in "$*"; do
echo $ARG
done
echo "================================="
echo "NOT Quoted DOLLAR-STAR"
for ARG in $*; do
echo $ARG
done
echo "================================="
이제 다양한 인수로 테스트 스크립트를 실행하십시오.
# ./test.sh "arg with space one" "arg2" arg3
=================================
Quoted DOLLAR-AT
arg with space one
arg2
arg3
=================================
NOT Quoted DOLLAR-AT
arg
with
space
one
arg2
arg3
=================================
Quoted DOLLAR-STAR
arg with space one arg2 arg3
=================================
NOT Quoted DOLLAR-STAR
arg
with
space
one
arg2
arg3
=================================
#!/usr/bin/env bash
while [ "$1" != "" ]; do
echo "Received: ${1}" && shift;
done;
args가 스크립트에 어떻게 들어오는 지 테스트 할 때 이것이 더 유용 할 것이라고 생각했습니다.
$#
""
, ''
어떤 인수가 없다면 또한 침묵, 인수로. 이 문제를 해결하려고했지만 for 루프와 카운터가 필요합니다 $#
. 방금 끝에 이것을 추가했습니다.echo "End of args or received quoted null"
$@
다른 문자와 함께 따옴표로 묶은 문자열에 포함하면 여러 인수가있을 때 동작이 매우 이상하며 첫 번째 인수 만 따옴표 안에 포함됩니다.
예:
#!/bin/bash
set -x
bash -c "true foo $@"
수율 :
$ bash test.sh bar baz
+ bash -c 'true foo bar' baz
그러나 먼저 다른 변수에 할당하십시오.
#!/bin/bash
set -x
args="$@"
bash -c "true foo $args"
수율 :
$ bash test.sh bar baz
+ args='bar baz'
+ bash -c 'true foo bar baz'
"$@"
bash 의 의미 내에서 의미가 있습니다. 또한와의 주요 차이점 $@
과 $*
두 가지가 모두 유용한 이유를 설명하는 데 도움이됩니다. 로부터 bash(1)
man 페이지 특수 매개 변수 섹션 : " *
- 확장 따옴표 내에서 발생하는 경우, 각 매개 변수, [...] 즉의 값을 하나의 단어로 확장 "$*"
동등하는하는 "$1c$2c..."
곳 c
이다 $IFS
]." 실제로 첫 번째 예제 $*
대신 $@
대신를 사용하면 두 번째 버전과 동일한 출력을 얻을 수 있습니다.
"$@"
. 다시 사람이 페이지에서 : " @
. - 확장 따옴표 내에서 발생하는 경우, 각 매개 변수는 별도의 단어로 확장 즉, "$@"
동일합니다 "$1"
"$2"
이중 인용 확장이 단어 내에서 발생하는 경우, 첫 번째 매개 변수의 확장이 가입되어 ... "는 원래 단어의 시작 부분과 함께 마지막 매개 변수의 확장은 원래 단어의 마지막 부분과 결합됩니다." ... 그리고 실제로 코드가 있었다면 net bash -c "true foo $@ bar baz"
처럼 코드 를 실행하십시오 . test.sh one two
bash -c 'true foo one' 'two bar baz'
$*
, 나는 그것이 존재한다는 것을 잊지 것 같다 ..
$@
처음으로 쉘 스크립팅을 시작할 때 견인력을 얻고 있었지만 여전히 거기에 있다는 것을 상기시켜야합니다. "$*"
스크립트에서 사용되는 것이 일반적이었습니다 . 그러면 저자는 모든 인수를 함께 스매싱한다는 것을 알고 있었기 때문에 단어 분리와 함께 복잡한 말도 안되는 모든 방식을 시도 "$*"
하거나 루핑을 통해 arg 목록을 재구성합니다. 이상 shift
만 사용 ... 하나 하나 아래를 당겨 $@
을 해결해에게 그것을. (즉 bash는도 액세스 배열 구성원에 같은 연상 기호를 사용하는 데 도움을줍니다 : ${var[*]}
그들 모두를위한 단어로, ${var[@]}
단어의 목록.)
bash -c
전혀 이해가되지 않는 방식으로 사용 하고 있다는 것입니다.
여기에 많은 대답이 권장 $@
되거나 $*
인용되지 않고 인용되지만, 이것이 실제로하는 일과 왜 그렇게 해야하는지 설명하는 사람은 없습니다. 이 답변 에서이 훌륭한 요약을 훔치도록하겠습니다 .
따옴표는 모든 차이를 만들며 따옴표가 없으면 동일한 동작을합니다.
내 목적을 위해 하나의 스크립트에서 다른 스크립트로 매개 변수를 전달해야했으며 최상의 옵션은 다음과 같습니다.
# file: parent.sh
# we have some params passed to parent.sh
# which we will like to pass on to child.sh as-is
./child.sh $*
따옴표가 없으며 $@
위의 상황에서도 잘 작동합니다.
bar "$@"
에 해당합니다 bar "$1" "$2" "$3" "$4"
따옴표가 중요합니다!
"$@"
, $@
, "$*"
또는 $*
이에 설명 된대로 탈출 및 연결에 관한 것이다 각 행동하라 약간 다른 유래 대답 .
밀접하게 관련된 유스 케이스 하나는 다음 과 같이 인수 안에 주어진 모든 인수를 전달하는 것입니다.
bash -c "bar \"$1\" \"$2\" \"$3\" \"$4\""
.
나는 이것을 달성하기 위해 @kvantour의 변형을 사용합니다.
bash -c "bar $(printf -- '"%s" ' "$@")"