programing

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

cafebook 2023. 4. 23. 11:28
반응형

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;

스크립트에 arg가 어떻게 들어가는지 테스트할 때 이 방법이 좀 더 유용할 것 같아서요.

다음을 포함하면$@따옴표로 묶인 문자열에서 여러 개의 인수가 있을 경우 동작이 매우 이상하며 첫 번째 인수만 따옴표 안에 포함됩니다.

예:

#!/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 "${@}"

덧붙여서, 이 스크립트는 UNIX에서도 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/3190818/pass-all-arguments-from-bash-script-to-another-command

반응형