Bash 셸 스크립트에서 모든 인수 전파
저는 다른 스크립트를 호출하는 매우 간단한 스크립트를 작성하고 있으며, 현재 스크립트의 매개 변수를 실행 중인 스크립트로 전파해야 합니다.
예를 들어, 제 스크립트 이름은foo.sh
및 호출bar.sh
.
foo.sh :
bar $1 $2 $3 $4
각 매개 변수를 명시적으로 지정하지 않고 어떻게 이 작업을 수행하려면 어떻게 해야 합니까?
사용하다"$@"
평이한 것이 아니라$@
매개 변수가 실제로 동일하게 전달되기를 원하는 경우.
관찰:
$ cat no_quotes.sh
#!/bin/bash
echo_args.sh $@
$ cat quotes.sh
#!/bin/bash
echo_args.sh "$@"
$ cat echo_args.sh
#!/bin/bash
echo Received: $1
echo Received: $2
echo Received: $3
echo Received: $4
$ ./no_quotes.sh first second
Received: first
Received: second
Received:
Received:
$ ./no_quotes.sh "one quoted arg"
Received: one
Received: quoted
Received: arg
Received:
$ ./quotes.sh first second
Received: first
Received: second
Received:
Received:
$ ./quotes.sh "one quoted arg"
Received: one quoted arg
Received:
Received:
Received:
bash 및 기타 Bourne 유사 쉘의 경우:
bar "$@"
사용하다"$@"
(모든 POSIX 호환에 사용 가능).
[...] , bash에는 공백으로 구분된 모든 명령줄 매개 변수로 확장되는 "$@" 변수가 있습니다.
예를 들어 Bash에서 왔습니다.
저는 이것이 잘 해결되었다는 것을 알지만, 여기 "$@" $*와 "$*" 사이의 비교가 있습니다.
테스트 스크립트의 내용:
# 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
=================================
여기에 있는 많은 답변들이 추천합니다.$@
또는$*
인용문이 있든 없든, 그러나 아무도 이것들이 실제로 무엇을 하는지 그리고 왜 당신이 그렇게 해야 하는지 설명해주지 않는 것 같습니다.다음 답변에서 이 훌륭한 요약을 발췌해 보겠습니다.
+--------+---------------------------+
| Syntax | Effective result |
+--------+---------------------------+
| $* | $1 $2 $3 ... ${N} |
+--------+---------------------------+
| $@ | $1 $2 $3 ... ${N} |
+--------+---------------------------+
| "$*" | "$1c$2c$3c...c${N}" |
+--------+---------------------------+
| "$@" | "$1" "$2" "$3" ... "${N}" |
+--------+---------------------------+
따옴표를 사용하면 모든 차이가 있지만 따옴표를 사용하지 않으면 둘 다 동일한 동작을 합니다.
제 목적을 위해 한 스크립트에서 다른 스크립트로 매개 변수를 있는 그대로 전달해야 했습니다. 이를 위해 최선의 옵션은 다음과 같습니다.
# 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 $*
인용문 없음 및$@
위의 상황에서도 작동해야 합니다.
#!/usr/bin/env bash
while [ "$1" != "" ]; do
echo "Received: ${1}" && shift;
done;
단지 이것이 어떻게 인수가 스크립트에 들어오는지 테스트할 때 조금 더 유용할 수 있다고 생각했습니다.
포함할 경우$@
따옴표로 묶인 문자열에서 여러 개의 인수가 있을 때 동작이 매우 이상하며 첫 번째 인수만 따옴표 안에 포함됩니다.
예:
#!/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'
내 SUN Unix에는 "$@"도 원하는 것으로 해석되지 않을 정도로 많은 제한이 있습니다.해결 방법은 ${@}입니다.예를들면,
#!/bin/ksh
find ./ -type f | xargs grep "${@}"
그나저나, 내 유닉스도 grep-r을 지원하지 않기 때문에 나는 이 특정 스크립트를 가지고 있어야 했습니다.
때때로 모든 인수를 전달하고 싶지만 플래그(예: 플래그)가 앞에 나옵니다.--flag
)
$ bar --flag "$1" --flag "$2" --flag "$3"
이 작업은 다음과 같은 방법으로 수행할 수 있습니다.
$ bar $(printf -- ' --flag "%s"' "$@")
참고: 추가 필드 분할을 방지하려면 따옴표를 사용해야 합니다.%s
그리고.$@
단일 문자열을 사용하지 않으려면 다음의 하위 셸을 인용할 수 없습니다.printf
.
bar "$@"
와 동등할 것입니다.bar "$1" "$2" "$3" "$4"
따옴표는 중요합니다!
"$@"
,$@
,"$*"
또는$*
이 스택 오버플로 답변에 설명된 대로 이스케이프 및 연결과 관련하여 각각 약간 다르게 동작합니다.
하나의 밀접한 관련이 있는 사용 사례는 다음과 같은 인수 내부에 주어진 모든 인수를 전달하는 것입니다.
bash -c "bar \"$1\" \"$2\" \"$3\" \"$4\""
.
저는 이를 달성하기 위해 @kvantour의 다양한 답변을 사용합니다.
bash -c "bar $(printf -- '"%s" ' "$@")"
공백이나 이스케이프 문자가 있는 경우를 제외하고는 정상적으로 작동합니다.이 경우 인수를 캡처하여 스크립트 내부의 SSH로 보낼 수 있는 방법을 찾을 수 없습니다.
이것은 유용할 수 있지만 너무 못생겼습니다.
_command_opts=$( echo "$@" | awk -F\- 'BEGIN { OFS=" -" } { for (i=2;i<=NF;i++) { gsub(/^[a-z] /,"&@",$i) ; gsub(/ $/,"",$i );gsub (/$/,"@",$i) }; print $0 }' | tr '@' \' )
"${array[@]}"
bash에서 배열을 전달하는 올바른 방법입니다.저는 논쟁을 준비하고 우회하고 처리하는 방법인 완전한 치트 시트를 제공하고 싶습니다.
pre.sh
->foo.sh
->bar.sh
.
#!/bin/bash
args=("--a=b c" "--e=f g")
args+=("--q=w e" "--a=s \"'d'\"")
./foo.sh "${args[@]}"
#!/bin/bash
./bar.sh "$@"
#!/bin/bash
echo $1
echo $2
echo $3
echo $4
결과:
--a=b c
--e=f g
--q=w e
--a=s "'d'"
언급URL : https://stackoverflow.com/questions/4824590/propagate-all-arguments-in-a-bash-shell-script
'IT' 카테고리의 다른 글
파일의 시작 부분에 텍스트를 삽입하는 방법은 무엇입니까? (0) | 2023.05.28 |
---|---|
깃 저장소에 대한 명명 규칙이 있습니까? (0) | 2023.05.28 |
"변경사항이 커밋을 위해 준비되지 않음"은 무엇을 의미합니까? (0) | 2023.05.28 |
$0 및 BASH_SOURCE 중에서 선택 (0) | 2023.05.28 |
git의 분기 간 커밋 차이를 보려면 어떻게 해야 합니까? (0) | 2023.05.28 |