IT

Bash 셸 스크립트에서 모든 인수 전파

itgroup 2023. 5. 28. 20:35
반응형

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

반응형