쉘 스크립트에서 ${1+"$@"}는 무엇을 의미하며 "$@"와는 어떻게 다릅니까?

쉘 스크립트에서 ${1+"$@"}는 무엇을 의미하며 "$@"와는 어떻게 다릅니까?

Perl 문서에서는페렌(1)Perl 스크립트를 실행하려면 이중 언어 쉘/Perl 헤더를 사용하는 것이 좋습니다.

#!/bin/sh
#! -*-perl-*-
eval 'exec perl -x -wS $0 ${1+"$@"}'
    if 0;

무슨 뜻이에요 ${1+"$@"}? (Bash를 /bin/sh로 사용) 사용해 보았는데 "$@"잘 작동하는 것 같았습니다.


편집하다

아래 두 가지 답변은 ${1:+"$@"}. 나는 ${parameter:+word}bash(1)에 문서화된 ("대체 값 사용") 구문을 알고 있습니다. 그러나 나는 그것을 믿지 않는다. 왜냐하면

  1. ${1+"$@"}매개변수 없이도 둘 다 잘 작동합니다. "$@"simple.sh를 다음과 같이 생성하면

    #!/bin/sh
    eval 'exec /usr/bin/perl -x -S -- $0 "$@"'
        if 0;
    #!perl
    use Data::Dumper;
    print Dumper(\@ARGV);
    

    그리고 Question.sh는 다음과 같습니다.

    #!/bin/sh
    eval 'exec /usr/bin/perl -x -S -- $0 ${1+"$@"}'
        if 0;
    #!perl
    use Data::Dumper;
    print Dumper(\@ARGV);
    

    둘 다 같은 방식으로 작동하게 할 수 있습니다.

    $ ./question.sh 
    $VAR1 = [];
    $ ./question.sh a
    $VAR1 = [
              'a'
            ];
    $ ./question.sh a 'b c'
    $VAR1 = [
              'a',
              'b c'
            ];
    $ ./question.sh ""
    $VAR1 = [
              ''
            ];
    $ ./simple.sh 
    $VAR1 = [];
    $ ./simple.sh a
    $VAR1 = [
              'a'
            ];
    $ ./simple.sh a 'b c'
    $VAR1 = [
              'a',
              'b c'
            ];
    $ ./simple.sh ""
    $VAR1 = [
              ''
            ];
    
  2. 다음을 포함하여 인터넷의 다른 소스도 사용됩니다 ${1+"$@"}.해커자기가 무슨 짓을 하는지 아는 것 같았던 사람.

${parameter+word}문서화되지 않은 대체(또는 더 이상 사용되지 않는) 구문 일까요 ${parameter:+word}? 이 가설을 확인할 수 있는 사람이 있나요?

답변1

이는 Bourne 쉘과의 호환성을 위한 것입니다. Bourne 쉘은 1979년 Unix 버전 7과 함께 처음 출시되었으며 /bin/sh1990년대 중반까지 대부분의 상용 Unices에서 일반적으로 사용되었던 고대 쉘입니다.

대부분의 사람들의 조상이다.본 같은 껍질ksh, 또는 .bashzsh

ksh여기에는 몇 가지 어색한 기능이 있으며 그 중 많은 기능이 다른 쉘 및 새로운 표준 사양에서 수정 되었습니다 sh. 그 중 하나는 다음과 같습니다.

Bourne 쉘의 경우(적어도 아직 수정되지 않은 변형): 인수가 전혀 없는 대신 "$@"위치 인수 목록이 비어 있으면( $# == 0) 빈 인수로 확장합니다.

${var+something}$var설정되지 않은 경우 '무언가'로 확장됩니다. 모든 쉘에 명확하게 문서화되어 있지만 bash다음 문장에 주의를 기울여야 하기 때문에 문서에서 찾기가 어렵습니다 .

하위 문자열 확장이 수행되지 않으면 bash는 아래 문서화된 형식을 사용하여 설정되지 않았거나 null인 인수를 테스트합니다. 콜론을 생략하면 설정되지 않은 매개변수만 테스트됩니다..

${1+"$@"}따라서 Bourne 쉘의 제한 사항을 해결하는 ( ) 설정 시에만 확장됩니다 ."$@"$1$# > 0

Bourne 쉘은 이 문제가 있는 유일한 쉘입니다. 최신 s( POSIX 사양을 sh준수함 (Bourne 쉘은 그렇지 않음))에는 이 문제가 없습니다. 따라서 매우 오래된 시스템에서 작동하는 코드가 필요한 경우에만 이 작업을 수행하면 됩니다. 표준 쉘 대신 Bourne 쉘이 될 수 있습니다(POSIX는 표준이 어디에 있는지 지정하지 않으므로 예를 들어 Solaris 11 이전의 Solaris에서는 , 여전히 Bourne 쉘(특정 문제는 아니지만), 일반/표준 은 다른 위치( )에 있습니다.shsh/bin/shsh/bin/shsh/usr/xpg4/bin/sh

Perldoc 페이지가 참조되지 않는데 perlrun문제가 있습니다.$0

바라보다http://www.in-ulm.de/~mascheck/various/bourne_args/더 많은 정보를 알고 싶습니다.

답변2

둘 사이에는 다음과 같은 차이점이 있습니다.

command ""

그리고

command

어떤 경우에는 전달하는 인수가 빈 문자열입니다. 두 번째에서는 0개의 인수가 전달됩니다.

두 경우 모두 "$@"는 다음과 같습니다 "". 하지만 사용은 첫 번째 항목에 대한 ${1:+"$@"}것이며 ""두 번째 항목에는 매개변수가 전달되지 않습니다. 이것이 의도입니다.

대화형 셸을 얻기 위해 선택적 명령을 사용하거나 인수 없이 호출할 수 있는 아래 스크립트(sshwrapper라고 함)를 실행하는 경우 이는 중요합니다.

: sshwrapper [command]
exec /usr/bin/ssh "${HOSTNAME:-localhost}" "$@"

이는 대화형 쉘이 아닌 원격 호스트(반환만)에서 "" 실행을 시도합니다.

: sshwrapper [command]
exec /usr/bin/ssh "${HOSTNAME:-localhost}" ${1:+"$@"}

exec가 변수를 빈 문자열이 아닌 null로 올바르게 해석하기 때문에 대화형 셸이 원격 호스트에서 시작됩니다.

"${parameter:+word}"("대체 값 사용") 및 유사한 변수 확장 문자열의 사용법은 bash 매뉴얼 페이지를 읽어보세요.

답변3

나는 Stéphane Chazelas의 답변을 요약했습니다.

  • ${1:+"$@"}' $1이 비어 있는지 또는 설정되지 않았는지 테스트합니다.
  • ${1+"$@"}'는 $1이 설정되지 않았는지 테스트합니다.

그래서 두 번째 매개변수 ""를 사용하면 $1이 비어 있다는 뜻인데 비어 있는지 테스트하지 않고 설정된 것으로만 보고 비어 있으면 $@을 확장하게 됩니다. ""와 함께 ${1:+"$@"}'를 사용하면 더 이상 확장되지 않습니다 $@.

관련 정보