소스 스크립트에 전달된 매개변수가 잘못되었습니다.

소스 스크립트에 전달된 매개변수가 잘못되었습니다.

전달된 인수 수를 확인하고 잘못된 경우 경고하는 AIX의 스크립트:-

if [ "$#" -ge 1 ]; then
  ...
else
  echo 'Usage: myscript <a> [b] [c]'
fi

스크립트는 이를 가져오기 위해 일부 환경 변수를 설정합니다. 즉, 명령줄에 다음을 입력합니다. 두 번째 스크립트가 없습니다. 다른 스크립트에서 스크립트를 가져오지 않습니다.

. ./myscript.sh

인수를 전달하지 않으면 using 문을 인쇄하고 싶지만 이전 명령에 전달된 인수를 사용하여 실행합니다(반드시 이 스크립트일 필요는 없습니다!).

이를 다시 확인하기 위해 스크립트 시작 부분에 다음 줄을 추가하여 이것이 사실임을 증명했습니다.

echo $# $@

매개변수를 전달하지 않으면 이전 소스 스크립트의 매개변수 수와 목록이 인쇄됩니다.

0개의 인수를 전달하고 다시 가져올 때 0이 되도록 하려면 어떻게 해야 합니까 $#?

가능한 가장 작은 재창조는 스크립트이므로:-

myscript.sh

echo $# $@

그런 다음 실행하십시오 :-

. ./myscript.sh a b c

인쇄하다

3 a b c

그런 다음 인수 없이 다시 실행하십시오.

. ./myscript.sh

같은 결과를 출력한다

3 a b c

인쇄할 것으로 예상되는 경우

0

스크립트를 얻지 못하고 직접 실행하는 경우:-

./myscript.sh

그런 다음 예상대로 작동하고 인쇄됩니다.

0

이것이 현재 문제를 명확하게 해주기를 바랍니다.

위의 방법이 왜 작동하지 않는지 설명하는 답변은 많이 받고 어떻게 해야 하는지에 대한 답변은 없는 것 같아서 다시 시도해 보고 제가 무엇을 하려는지 설명해야겠다고 생각했습니다.

필요하다

최소한 하나의 인수가 필요한 스크립트를 작성해야 하며, 해당 인수로 호출되지 않으면 불평하고(위 질문의 첫 번째 코드 부분 참조) 스크립트는 일부 환경 변수를 설정해야 합니다. 두 번째 요구 사항 때문에 스크립트가 완료될 때 환경 변수가 계속 설정되도록 스크립트를 가져와야 한다고 가정합니다. 매개변수가 전달되지 않은 시기를 알려주고 환경 변수도 설정하는 스크립트를 어떻게 작성합니까?

답변1

존재하다

. path/to/script at least one argument

다른 사람들이 말했듯이, 쉘에 따라 이러한 추가 매개변수는 무시되거나(Bourne, Almquist) 스크립트가 해석될 때 현재 위치 매개변수 세트( $@, $1, ...)를 대체합니다(대부분의 다른 쉘). $2POSIX는 추가 인수가 에 전달될 때의 동작을 지정하지 않습니다 .. 이 경우 set a b스크립트의 위치 매개변수(예: )에 대한 변경 사항이 완료 후에도 유지되는지 여부에 대해 셸 간에 약간의 차이가 있습니다 ..

존재하다:

. path/to/script

그러나 동작이 지정됩니다. 위치 매개변수가 필요합니다.아니요영향을 받으므로 스크립트 해석은 이전과 동일하게 유지됩니다.

이 스크립트를 해석하는 동안 위치 매개변수를 빈 목록으로 만들려면 미리 재설정하거나 다음 함수를 사용해야 합니다.

set -- # or shift "$#"
. path/to/script

(위치 매개변수는 손실되지만) 또는 다음 기능을 사용하세요.

dot() { file=$1; shift; . "$file"; }
dot path/to/myscript

명령을 실행할 때 .위치 매개변수는 함수의 위치 매개변수가 됩니다. 나중에 shift함수에 전달되는 인수에서 첫 번째 인수를 뺀 값이 되므로 위는 빈 목록이지만 이는 함수를 사용하면 다음과 같이 임의의 인수 목록을 소스 스크립트에 전달할 수 있음을 의미합니다.

dot path/to/myscript extra args

이는 소스 스크립트에서 제공됩니다 extra args.$1$2

myscript호출이 위치 인수 목록을 수정하는 경우 set함수의 위치 인수만 영향을 받으며 이러한 변경 사항은 함수가 반환된 후에 유지되지 않습니다.

답변2

배쉬 도움말 텍스트 .:

.: . filename [arguments]
    Execute commands from a file in the current shell.

    Read and execute commands from FILENAME in the current shell.  The
    entries in $PATH are used to find the directory containing FILENAME.
    If any ARGUMENTS are supplied, they become the positional parameters
    when FILENAME is executed.

이 문장에 주목하세요: "만약에인수를 제공하지 마십시오." 인수가 제공되지 않으면 현재 위치 인수가 유지됩니다.

$ cat /tmp/sourceme.sh     
printf "%d: " "$#"
printf "<%s> " "$@"
printf "\n"
$ bash -c 'set -- aa bb; . /tmp/sourceme.sh'
2: <aa> <bb> 
$ bash -c 'set -- aa bb; . /tmp/sourceme.sh foo bar'
2: <foo> <bar> 

내가 테스트한 다른 모든 쉘(zsh, ksh)도 비슷하게 작동합니다. 제외하고 dash, 어느언제나원래 위치 매개변수를 유지합니다.

$ dash -c 'set -- aa bb; . /tmp/sourceme.sh foo bar'
2: <aa> <bb> 

위치 매개변수 재설정에 대한 언급이 없습니다.POSIX 정의..그래서 처음부터 논증을 하는 것은 비표준적인 것 같습니다 .


함수는 표준 셸의 인수를 허용하므로 소스 스크립트 대신 함수를 사용할 수 있습니다. 이 경우 함수를 정의하는 파일을 얻습니다.

define_fun.sh예를 들어, 함수 정의가 있는 파일( ):

#!/bin/sh
f() {
    echo "args: $# $@"     # just a test
    if [ "$#" = 0 ]; then 
        echo please give at least one argument
        return 1
    fi;
    ENVVAR=$1          # this should be visible to the whole shell  
    export ENVVAR      # and any commands called later
} 

그런 다음 사용하십시오.

$ . define_fun.sh      # source the file to load the func in the current shell

$ f                    # actually run it: this'll complain
$ f 123 456            # this should set ENVVAR
$ echo $ENVVAR         # and this will print '123'

쉘의 초기화 파일 중 하나에 함수 정의를 배치할 수 있습니다( ~/.profile?는 쉘에 따라 다릅니다.)

답변3

dot내장 명령 에 인수를 전달하는 것은 Korn 쉘 확장이며 다른 쉘에서는 허용되지 않습니다.

POSIX 표준에서는 도트 명령에 대해 $# 및 $@를 언급하지 않으므로 현재 셸의 매개 변수는 도트 명령에 표시되므로 다음과 같이 셸을 호출하면:

myshell -s a b c

그럼 전화해

. ./myscript.sh

인쇄할 것으로 예상됨

3 a b c

관련 정보