중첩 스크립트에서 안전하게 수신 할 수 있도록 bash 스크립트의 인용 된 매개 변수를 얻으려고합니다. 어떤 아이디어?
test.sh
#!/bin/bash
echo $*
bash myecho.sh $*
myecho.sh
#!/bin/bash
echo $1
echo $2
echo $3
echo $4
견본:
bash test.sh aaa bbb '"ccc ddd"'
결과:
aaa bbb "ccc ddd"
aaa
bbb
"ccc
ddd"
원하는 결과
aaa bbb "ccc ddd"
aaa
bbb
ccc ddd
답변
#!/bin/bash
echo $*
bash myecho.sh "$@"
“$ @”구조는 bash에 한정되지 않으며 모든 POSIX 쉘에서 작동해야합니다 (적어도 대시에서는 작동 함). 또한 원하는 출력이 주어지면 추가 수준의 인용이 필요하지 않습니다. IE는 위의 스크립트를 다음과 같이 호출합니다.
./test.sh 1 2 "3 4"
답변
“$ @”(따옴표로 묶인 달러)를 사용하여 매개 변수를 아래 첨자로 전달하려고합니다. 이렇게 ….
ls-color.sh:
#!/bin/bash
/bin/ls --color=auto "$@" # passes though all CLI-args to 'ls'
이유는 …..
로부터 배쉬 man 페이지 :
$*
-1부터 시작하여 위치 매개 변수로 확장됩니다. 큰 따옴표 안에 확장이 발생하면 IFS 특수 변수의 첫 번째 문자로 구분 된 각 매개 변수의 값이있는 단일 단어로 확장됩니다. 즉,"$*"
와 동일합니다
"$1c$2c..."
. 여기서 c는 IFS 변수 값의 첫 번째 문자입니다. IFS가 설정되지 않은 경우 매개 변수는 공백으로 구분됩니다. IFS가 널인 경우 매개 변수는 구분 기호없이 결합됩니다.
$@
-1부터 시작하여 위치 매개 변수로 확장됩니다. 큰 따옴표 안에 확장이 발생하면 각 매개 변수가 별도의 단어로 확장됩니다. 즉,"$@"
동등"$1" "$2" ...
이중 인용 확장 단어 내에서 발생하는 경우, 상기 제 파라미터의 확장은 일본어 단어의 시작 부분에 접합되고, 최종 파라미터의 확장은 기존의 마지막 부분에 접합되고 워드. 거기에는 위치 매개 변수가 없을 때
"$@"
와$@
아무것도 확장 (즉, 그들은 제거된다).
데모 스크립트 설정 …
echo 'echo -e "\$1=$1\n\$2=$2\n\$3=$3\n\$4=$4"' > echo-params.sh
echo './echo-params.sh $*' > dollar-star.sh
echo './echo-params.sh $@' > dollar-at.sh
echo './echo-params.sh "$*"' > quoted-dollar-star.sh
echo './echo-params.sh "$@"' > quoted-dollar-at.sh
chmod +x *.sh
"$@"
-quoted-dollar-at는 args를 서브 쉘로 다시 전달하기위한 신원 변환 입니다 (약 99 %의 시간, 이것이 당신이 의도 한 것입니다) :
./quoted-dollar-at.sh aaa '' "'cc cc'" '"ddd ddd"'
# $1= aaa
# $2=
# $3= 'cc cc'
# $4= "ddd ddd"
"$*"
-quoted -dollar-star 는 args를 단일 문자열로 분쇄합니다 (실제로이 동작을 원하는 시간의 ~ 1 %, 예 : 조건부 🙂 if [[ -z "$*" ]]; then ...
:
./quoted-dollar-star.sh aaa '' "'cc cc'" '"ddd ddd"'
# $1= aaa 'cc cc' "ddd ddd"
# $2=
# $3=
# $4=
$*
/ $@
-따옴표없이 두 형식 모두 한 수준의 따옴표를 제거하고 기본 문자열에서 공백을 해석하지만 따옴표 문자는 무시합니다 (거의 항상 이것은 실수입니다).
./dollar-star.sh aaa '' "'cc cc'" '"ddd ddd"'
# $1= aaa
# $2= 'cc
# $3= cc'
# $4= "ddd
./dollar-at.sh aaa '' "'cc cc'" '"ddd ddd"'
# $1= aaa
# $2= 'cc
# $3= cc'
# $4= "ddd
재미를 원한다면 “$ @”를 사용하여 원하는만큼 깊이 중첩하고, 원하는 경우 args 스택에서 요소를 밀어 내고 터뜨릴 수 있습니다.
function identity() {
"$@"
}
set -x
identity identity identity identity identity echo Hello \"World\"
# + identity identity identity identity identity echo Hello '"World"'
# + identity identity identity identity echo Hello '"World"'
# + identity identity identity echo Hello '"World"'
# + identity identity echo Hello '"World"'
# + identity echo Hello '"World"'
# + echo Hello '"World"'
# Hello "World"