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


43

Perl 문서에서 perlrun (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}무엇입니까? 누군가 그 가설을 확인할 수 있습니까?


답변:


53

그것은 Bourne 쉘과의 호환성을위한 것입니다. Bourne 쉘은 1979 년에 Unix 버전 7로 처음 릴리스 된 오래된 쉘이었으며 /bin/sh대부분의 상용 Unices에서 와 마찬가지로 90 년대 중반까지 계속 사용되었습니다 .

그것은 대부분의 조상 본쉘 과 같은 ksh, bash또는 zsh.

많은 기능이 수정되었으며 ksh다른 쉘과 새로운 표준 사양 sh중 하나 인이 몇 가지 어색한 기능을 가지고 있습니다 .

Bourne 쉘 (적어도 수정되지 않은 변형) : "$@"위치 매개 변수 목록이 인수가 $# == 0아닌 빈 ( ) 인 경우 하나의 빈 인수로 확장됩니다 .

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

하위 문서 확장을 수행하지 않을 때 아래에 설명 된 양식을 사용하여 bash는 설정되지 않았거나 널인 매개 변수를 테스트합니다. 콜론을 생략하면 설정되지 않은 매개 변수에 대해서만 테스트가 수행됩니다 .

따라서 Bourne 쉘의 해당 제한을 해결하는 set ( ) ${1+"$@"}으로 "$@"만 확장됩니다 .$1$# > 0

Bourne 쉘은 해당 문제점이있는 유일한 쉘입니다. 현대 sh의 ( Bourne 쉘이 아닌 shPOSIX 사양을 준수하는 sh) 해당 문제가 없습니다. 따라서 /bin/sh표준 쉘 대신 Bourne 쉘이 될 수있는 매우 오래된 시스템에서 코드를 작동시켜야하는 경우에만 필요합니다 (POSIX는 표준 위치를 지정하지 않습니다. sh예를 들어 Solaris 11 이전의 Solaris에서는, /bin/sh표준 / 표준 sh이 다른 위치에있는 동안 여전히 Bourne 쉘이었습니다 (특정 문제는 없었지만 /usr/xpg4/bin/sh).

perlrunperldoc 페이지 $0에는 인용되지 않은 문제가 있습니다 .

자세한 내용은 http://www.in-ulm.de/~mascheck/various/bourne_args/ 를 참조하십시오.


가보로는 재생할 수 없습니다. 아마도 Solaris에는 해당되지 않습니다.
ormaaj

2
@ormaaj. 예, 링크 된 페이지를 참조하십시오. SVR3에서 수정되었으며 Solaris / SunOS 5 이상은 SVR4를 기반으로합니다. 그리고 그 페이지에는 4.1.x에도 문제가 없다고 언급되어 있습니다.
Stéphane Chazelas

아 알 겠어요 <3 Mascheck 페이지.
ormaaj

3

다음과 같은 차이점이 있습니다.

command ""

command

하나는 빈 문자열 인 하나의 인수를 전달하는 것입니다. 두 번째에는 전달 된 인수가 없습니다.

둘 다 "$ @"는 같은 것과 같습니다 : "". 그러나 사용하는 ${1:+"$@"}것이 ""제 의도했던 두 번째, 대한 전달 인수를 위해.

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

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

이것은 원격 호스트에서 ""를 실행하려고 시도하고 (방금 리턴) 대화식 쉘이 아닙니다.

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

exec가 변수를 빈 문자열이 아닌 아무것도 아닌 것으로 올바르게 해석하기 때문에 원격 호스트에서 대화식 쉘을 시작합니다.

bash 매뉴얼 페이지에서 "$ {parameter : + word}"( "대체 값 사용") 및 유사한 변수 확장 문자열 사용법을 읽으십시오.


이것은 POSIX 호환 구현 에는 적용 되지 않는 Bourne 쉘에만 적용되는 것으로 보입니다 sh(다른 답변 참조).
törzsmókus

4
아니요, 비어 ${1:+"$@"}있으면 인수가없는 것으로 확장됩니다 $1. 당신은 원합니다 ${1+"$@"}. 기본적으로 당신은 그것을 뒤집 었습니다.
Stéphane Chazelas

0

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

  • $ 1이 null이거나 설정되지 않은 경우 $ {1 : + "$ @"} '테스트
  • $ 1이 설정되지 않은 경우 $ {1 + "$ @"} '테스트

따라서 매개 변수 ""와 함께 두 번째 매개 변수를 사용하면 $ 1이 null임을 의미하지만 null인지 여부를 테스트하지는 않지만 이미 비어 있거나 설정되지 않았으므로 $ @ 확장됩니다. 하지만 $ {1 : + "$ @"} '을 ""와 함께 사용 $@하면 더 이상 확장되지 않습니다 .


7
명확하지 않을 수도 있지만 이것은 분명히 요약했습니다 ...
Archemar
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.