쉘 스크립트에 명명 된 인수 전달


114

명명 된 매개 변수를 쉘 스크립트로 전달 (수신)하는 쉬운 방법이 있습니까?

예를 들어

my_script -p_out '/some/path' -arg_1 '5'

그리고 내부 my_script.sh는 다음과 같이받습니다 :

# I believe this notation does not work, but is there anything close to it?
p_out=$ARGUMENTS['p_out']
arg1=$ARGUMENTS['arg_1']

printf "The Argument p_out is %s" "$p_out"
printf "The Argument arg_1 is %s" "$arg1"

Bash 또는 Zsh에서 가능합니까?


2
한 번 봐 가지고 docopt를 - 그것은 명명 된 매개 변수에 도움이 및 입력 검증도 않습니다
비트

답변:


34

가장 유사한 구문은 다음과 같습니다.

p_out='/some/path' arg_1='5' my_script

7
이와 관련하여 -k옵션이 호출 쉘에 설정된 my_script p_out='/some/path' arg_1='5'경우 동일한 효과가 있습니다. (지정 형식의 모든 인수는 명령 이전의 지정뿐만 아니라 환경에 추가됩니다.)
chepner

13
나는이 구문을 좋아했지만 큰 경고가 있습니다 : 명령 / 함수 실행 후에도 해당 변수는 여전히 현재 범위에서 정의됩니다! 예 : x=42 echo $x; echo $x의 다음 실행을 의미 my_script하는 경우, p_out생략,이 값에 충실 할 것이다 마지막 시간을 통과! ( '/some/path')
Lucas Cimon

@LucasCimon 당신은 할 수 없습니다 unset그 첫 번째 실행 한 후, 다음 실행하기 전에를 재설정?
Nikos Alexandris

2
@LucasCimon 맞지 않습니다. 이전에 정의되지 않은 x=42 echo $x경우 아무것도 출력하지 않습니다 $x.
Hauke ​​Laging

맞습니다 @HaukeLaging, 정정 해 주셔서 감사합니다
Lucas Cimon

147

당신이 즉, 단일 문자 인수 이름에 한정되는 괜찮다면 my_script -p '/some/path' -a5, 다음 bash는 당신은 내장 사용할 수 있습니다 getopts, 예를

#!/bin/bash

while getopts ":a:p:" opt; do
  case $opt in
    a) arg_1="$OPTARG"
    ;;
    p) p_out="$OPTARG"
    ;;
    \?) echo "Invalid option -$OPTARG" >&2
    ;;
  esac
done

printf "Argument p_out is %s\n" "$p_out"
printf "Argument arg_1 is %s\n" "$arg_1"

그럼 넌 할 수있어

$ ./my_script -p '/some/path' -a5
Argument p_out is /some/path
Argument arg_1 is 5

유용한 Small getopts 튜토리얼이 있거나 help getopts쉘 프롬프트에서 입력 할 수 있습니다 .


25
이것은 정답입니다
Kaushik Ghose

3
나는 이것이 조금 오래되었다는 것을 알고 있지만 왜 논쟁에 대해 단 1 글자입니까?
Kevin

1
나는 (그러나이 구현 i하고 d). 내가 그것을 실행할 때 인수에 my_script -i asd -d asd대한 빈 문자열을 얻습니다 d. 실행하면 my_script -d asd -i asd두 인수 모두에 빈 문자열이 표시됩니다.
Milkncookiez

3
@ Milkncookiez-비슷한 문제가 있습니다. 마지막 인수 뒤에 ':'을 포함시키지 않았습니다 (필자의 경우 'w'). ':'를 추가하면 예상대로 작동하기 시작했습니다.
Derek

37

drupal.org 에서 이것을 훔 쳤지 만 다음과 같이 할 수 있습니다.

while [ $# -gt 0 ]; do
  case "$1" in
    --p_out=*)
      p_out="${1#*=}"
      ;;
    --arg_1=*)
      arg_1="${1#*=}"
      ;;
    *)
      printf "***************************\n"
      printf "* Error: Invalid argument.*\n"
      printf "***************************\n"
      exit 1
  esac
  shift
done

유일한 경고는 구문을 사용해야한다는 것입니다 my_script --p_out=/some/path --arg_1=5.


7
경고는 필요하지 않습니다. :) 당신은 다음과 같은 조건을 가질 수 있습니다 :-c|--condition)
Milkncookiez

28

이 스크립트를 사용하고 매력처럼 작동합니다.

for ARGUMENT in "$@"
do

    KEY=$(echo $ARGUMENT | cut -f1 -d=)
    VALUE=$(echo $ARGUMENT | cut -f2 -d=)   

    case "$KEY" in
            STEPS)              STEPS=${VALUE} ;;
            REPOSITORY_NAME)    REPOSITORY_NAME=${VALUE} ;;     
            *)   
    esac    


done

echo "STEPS = $STEPS"
echo "REPOSITORY_NAME = $REPOSITORY_NAME"

용법

bash my_scripts.sh  STEPS="ABC" REPOSITORY_NAME="stackexchange"

콘솔 결과 :

STEPS = ABC
REPOSITORY_NAME = stackexchange

STEPSREPOSITORY_NAME을 (를) 스크립트에서 사용할 수 있습니다.

인수의 순서는 중요하지 않습니다.


4
이것은 깔끔하며 허용되는 답변이어야합니다.
miguelmorin

15

로에게 zsh, 당신은 사용하십시오 zparseopts:

#! /bin/zsh -
zmodload zsh/zutil
zparseopts -A ARGUMENTS -p_out: -arg_1:

p_out=$ARGUMENTS[--p_out]
arg1=$ARGUMENTS[--arg_1]

printf 'Argument p_out is "%s"\n' "$p_out"
printf 'Argument arg_1 is "%s"\n' "$arg_1"

그러나을 사용하여 스크립트를 호출합니다 myscript --p_out foo.

zparseopts긴 옵션 또는 축약 지원하지 않습니다 --p_out=fooGNU이 같은 구문을 getopt(3)수행합니다.


zparseopts가 인수에 대해 하나의 대시 만 사용하는 반면 []2 개의 대시는 왜 사용하는지 알고 있습니까? 말도 안 돼!
Timo

@Timo, 자세한 info zsh zparseopts내용 참조
Stéphane Chazelas

9

방금이 스크립트를 생각해 냈습니다

while [ $# -gt 0 ]; do

   if [[ $1 == *"--"* ]]; then
        v="${1/--/}"
        declare $v="$2"
   fi

  shift
done

이 같은 통과 my_script --p_out /some/path --arg_1 5후 스크립트에서 당신은 사용할 수 있습니다 $arg_1$p_out.


나는 KSH88에서이 솔루션을 좋아한다. v=``echo ${1} | awk '{print substr($1,3)}'`` typeset $v="$2"(한쪽에 하나의 백틱을 제거)
hol

-2

함수 나 응용 프로그램에 인수가 0 개 이상인 경우 항상 마지막 인수가 있습니다.

다음과 같이 옵션 플래그 및 값 쌍을 읽으려면 다음을 수행하십시오. $ ./t.sh -o output -i input -l last

가변 개수의 옵션 / 값 쌍을 허용하려고합니다.

거대한 "if .. then .. else .. fi"트리를 원하지 않습니다.

그런 다음 인수가 0이 아닌 짝수인지 확인한 후

이 네 개의 평가 문을 본문으로하여 while 루프를 작성하고 각 루프에서 결정된 두 값을 사용하여 case 문을 작성하십시오.

스크립팅의 까다로운 부분은 다음과 같습니다.

#!/bin/sh    

# For each pair - this chunk is hard coded for the last pair.
eval TMP="'$'$#"
eval "PICK=$TMP"
eval TMP="'$'$(($#-1))"
eval "OPT=$TMP"

# process as required - usually a case statement on $OPT
echo "$OPT \n $PICK"

# Then decrement the indices (as in third eval statement) 

:<< EoF_test
$ ./t.sh -o output -i input -l last
-l 
last
$ ./t.sh -o output -l last
-l 
last
$ ./t.sh  -l last
-l 
last
EoF_test

-3
mitsos@redhat24$ my_script "a=1;b=mitsos;c=karamitsos"
#!/bin/sh
eval "$1"

방금 스크립트 범위 안에 명령 줄 매개 변수를 삽입했습니다!


3
OP가 지정한 구문으로는 작동하지 않습니다. 그들은 원한다-a 1 -b mitsos -c karamitsos
Michael Mrozek
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.