[syntax] 쉘 스크립트에서 백틱 대신 $ ()를 사용하면 어떤 이점이 있습니까?

명령 행 출력을 캡처하는 두 가지 방법이 있습니다 bash.

  1. 레거시 Bourne 쉘 백틱 ``:

    var=`command`
  2. $() 구문 (내가 아는 한 Bash에만 해당되거나 최소한 원래 Bourne과 같은 POSIX가 아닌 오래된 쉘에서는 지원되지 않음)

    var=$(command)

백틱과 비교하여 두 번째 구문을 사용하면 어떤 이점이 있습니까? 아니면 두 사람이 완전히 100 % 동일합니까?



답변

주요한 것은 명령에 명령 을 중첩 시킬 수 있다는 것인데, 어떤 형태의 이스케이프가 백틱에서 작동하는지 알아 내려고 노력하는 정신을 잃지 않고 명령 내에 명령을 내릴 수 있습니다.

예를 들어, 다소 고안되었다.

deps=$(find /dir -name $(ls -1tr 201112[0-9][0-9]*.txt | tail -1l) -print)

/dir2011 년 12 월 (a) 의 가장 오래된 날짜의 텍스트 파일과 이름이 같은 디렉토리 트리 의 모든 파일 목록이 제공됩니다 .

또 다른 예는 상위 디렉토리의 이름 (전체 경로가 아님)을 얻는 것과 같습니다.

pax> cd /home/pax/xyzzy/plugh
pax> parent=$(basename $(dirname $PWD))
pax> echo $parent
xyzzy

(a) 이제 특정 명령이 실제로 작동하지 않을 수 있으므로 기능을 테스트하지 않았습니다. 그래서, 당신이 저에게 투표를한다면, 의도를 잃어버린 것입니다. 🙂 그것은 버그가없는 프로덕션 레디 스 니펫이 아니라 어떻게 네 스팅을 할 수 있는지에 대한 예시입니다.


답변

gcc설치된 위치에 해당하는 lib 디렉토리를 찾으려고 가정하십시오 . 선택하실 수 있습니다 :

libdir=$(dirname $(dirname $(which gcc)))/lib

libdir=`dirname \`dirname \\\`which gcc\\\`\``/lib

첫 번째는 두 번째보다 쉽습니다. 첫 번째를 사용하십시오.


답변

백틱 ( `...`)은 가장 오래된 비 POSIX 호환 bourne-shell에만 필요한 레거시 구문 $(...)이며 POSIX이며 몇 가지 이유로 더 선호됩니다.

  • \백틱 내부의 백 슬래시 ( )는 명확하지 않은 방식으로 처리됩니다.

    $ echo "`echo \\a`" "$(echo \\a)"
    a \a
    $ echo "`echo \\\\a`" "$(echo \\\\a)"
    \a \\a
    # Note that this is true for *single quotes* too!
    $ foo=`echo '\\'`; bar=$(echo '\\'); echo "foo is $foo, bar is $bar"
    foo is \, bar is \\
  • 중첩 된 인용문 $()이 훨씬 더 편리합니다.

    echo "x is $(sed ... <<<"$y")"

    대신에:

    echo "x is `sed ... <<<\"$y\"`"

    또는 다음과 같은 것을 작성하십시오.

    IPs_inna_string=`awk "/\`cat /etc/myname\`/"'{print $1}' /etc/hosts`

    $()인용을 위해 완전히 새로운 맥락을 사용 하기 때문에

    Bourne 및 Korn 쉘에는 이러한 백 슬래시가 필요하지만 Bash 및 대시는 필요하지 않으므로 이식성이 없습니다.

  • 중첩 명령 대체 구문이 더 쉽습니다.

    x=$(grep "$(dirname "$path")" file)

    보다:

    x=`grep "\`dirname \"$path\"\`" file`

    때문에 $()각 명령의 대체가 보호되고 인용과 이스케이프 이상 특별한 문제없이 자체적으로 처리 할 수 있도록 인용에 대한 완전히 새로운 상황 시행한다. 백틱을 사용하는 경우 레벨이 2 이상이되면 배가 더 나빠집니다.

    몇 가지 더 많은 예 :

    echo `echo `ls``      # INCORRECT
    echo `echo \`ls\``    # CORRECT
    echo $(echo $(ls))    # CORRECT
  • 역 따옴표를 사용할 때 일관되지 않은 동작 문제를 해결합니다.

    • echo '\$x' 출력 \$x
    • echo `echo '\$x'` 출력 $x
    • echo $(echo '\$x') 출력 \$x
  • Backticks 구문에는 포함 된 명령의 내용에 대한 기록 제한이 있으며, 역 따옴표를 포함하는 일부 유효한 스크립트를 처리 할 수 ​​없지만 최신 $()양식은 모든 종류의 유효한 포함 된 스크립트를 처리 할 수 ​​있습니다.

    예를 들어, 유효한 다른 내장 스크립트는 왼쪽 열에서 작동하지 않지만 오른쪽 IEEE 에서는 작동합니다 .

    echo `                         echo $(
    cat <<\eof                     cat <<\eof
    a here-doc with `              a here-doc with )
    eof                            eof
    `                              )
    
    
    echo `                         echo $(
    echo abc # a comment with `    echo abc # a comment with )
    `                              )
    
    
    echo `                         echo $(
    echo '`'                       echo ')'
    `                              )

따라서 $-prefixed 명령 대체 구문 은 선호하는 방법이어야합니다. 깨끗한 구문으로 시각적으로 명확하고 (인간 및 기계 가독성 향상) 중첩 가능하고 직관적이며 내부 구문 분석이 분리되어 있으며보다 일관성이 있습니다. 큰 따옴표 내에서 구문 분석되는 다른 모든 확장) (예 : 백틱이 유일한 예외이고 `문자가 인접 해있을 때 문자가 쉽게 위장 "되어 특히 작거나 특이한 글꼴로 읽기가 더 어려워 짐)

출처 : $(...)선호하는 이유는 무엇입니까 `...`(백틱)? BashFAQ에서

또한보십시오:


답변

남자 배쉬에서 :

          $(command)
   or
          `command`

   Bash performs the expansion by executing command and replacing the com-
   mand  substitution  with  the  standard output of the command, with any
   trailing newlines deleted.  Embedded newlines are not deleted, but they
   may  be  removed during word splitting.  The command substitution $(cat
   file) can be replaced by the equivalent but faster $(< file).

   When the old-style backquote form of substitution  is  used,  backslash
   retains  its  literal  meaning except when followed by $, `, or \.  The
   first backquote not preceded by a backslash terminates the command sub-
   stitution.   When using the $(command) form, all characters between the
   parentheses make up the command; none are treated specially.


답변

다른 답변 외에도

$(...)

시각적으로 눈에 띄는 것보다

`...`

백틱은 아포스트로피처럼 보입니다. 사용중인 글꼴에 따라 다릅니다.

(방금 알았 듯이 백틱은 인라인 코드 샘플에 입력하기가 훨씬 어렵습니다.)


답변

$() 중첩을 허용합니다.

out=$(echo today is $(date))

나는 백틱이 그것을 허용하지 않는다고 생각합니다.


답변

$(command)명령 대체 형식 을 정의하는 것이 POSIX 표준입니다 . 오늘날 사용되는 대부분의 쉘은 POSIX를 준수하며 기존의 백틱 표기법보다 선호되는 형식을 지원합니다. 쉘 언어 문서 의 명령 대체 섹션 (2.6.3)은 다음을 설명합니다.

명령 대체는 명령 이름 대신 명령 출력을 대체 할 수있게합니다. 명령 대체는 명령이 다음과 같이 묶여있을 때 발생합니다.

$(command)

또는 (backquoted version) :

`command`


은 서브 쉘 환경에서 명령 을 실행 하고 ( 쉘 실행 환경 참조 ) 명령 대체 ( 명령 텍스트와 “$ ()”또는 역 따옴표)를 명령의 표준 출력으로 대체하여 명령 대체를 확장해야합니다. <newline>대체가 끝날 때 하나 이상의 문자 시퀀스 . <newline>출력이 끝나기 전에 포함 된 문자는 제거되지 않아야합니다. 그러나 IFS의 값과 인용에 따라 필드 구분 기호로 필드 구분 기호로 처리되어 제거 될 수 있습니다. 출력에 널 바이트가 포함되어 있으면 동작이 지정되지 않은 것입니다.

역 인용 된 명령 대체 스타일 내에서 <backslash>$‘, ‘ `‘또는
뒤에 오는 경우를 제외하고 문자 그대로의 의미를 유지해야합니다 <backslash>. 일치하는 역 따옴표에 대한 검색은 인용되지 않은 첫 번째 인용되지 않은 역 따옴표에 의해 충족되어야합니다. 이 검색 중에 이스케이프 처리되지 않은 역 따옴표가 쉘 주석, 여기 문서, $ ( command ) 형식 의 내장 명령 대체 또는 인용 된 문자열에서 발견되면 정의되지 않은 결과가 발생합니다. ” `...`“시퀀스 내에서 시작하지만 끝나지 않는 작은 따옴표 또는 큰 따옴표 문자열 은 정의되지 않은 결과를 생성합니다.

$ ( command ) 형식을 사용하면 여는 괄호 뒤에 나오는 닫는 괄호 뒤에있는 모든 문자가 command를 구성합니다
. 지정되지 않은 결과를 생성하는 리디렉션만으로 구성된 스크립트를 제외하고 유효한 쉘 스크립트를 command에 사용할 수 있습니다 .

추가 틸드 확장, 파라미터 확장, 명령 대체 또는 산술 확장을 위해 명령 대체의 결과가 처리되지 않아야합니다. 큰 따옴표 안에 명령 대체가 발생하면 대체 결과에 대해 필드 분할 및 경로 이름 확장을 수행하지 않아야합니다.

명령 대체는 중첩 될 수 있습니다. 역 인용 버전 내에서 중첩을 지정하려면 응용 프로그램은 내부 역 인용 부호 앞에 <backslash>문자를 사용해야 합니다. 예를 들면 다음과 같습니다.

\`command\`

쉘 명령 언어의 구문에는 “로 시작하는 확장에 대한 모호성이 있습니다.$((하위 쉘로 시작하는 산술 확장 또는 명령 대체를 도입 할 수 있습니다. 산술 확장이 우선합니다. 즉, 쉘은 먼저 확장을 산술 확장으로 구문 분석 할 수 있는지 여부를 판별하고 확장을 명령으로 구문 분석해야합니다. 확장을 산술 확장으로 구문 분석 할 수없는 것으로 판단되는 경우 쉘은이 결정을 수행 할 때 중첩 된 확장을 평가할 필요가 없습니다. 확장을 산술 확장으로 구문 분석 할 수 없다고 결정하지 않고 입력 종료가 발생하면 쉘은 확장을 불완전한 산술 확장으로 취급하고 구문 오류를보고해야합니다. 적합한 응용 프로그램은 “$( “와 “(하위 쉘로 시작하는 명령 대체에서 두 개의 토큰 (즉, 공백으로 분리)으로 구분됩니다. 예를 들어, 단일 서브 쉘을 포함하는 명령 대체는 다음과 같이 작성 될 수 있습니다.

$( (command) )