쉘 스크립트에서 $ {}와 $ ()의 차이점


28
$ echo $(date)
Thu Jul 2 16:33:11 SGT 2015
$ echo ${date}

$ name=foo
$ echo $(name)
ksh: name:  not found

$ echo ${name}
foo

$ {variable}은 $ variable과 같습니다. $ ()는 명령을 실행하는 것입니다. 왜 $ {}을 사용합니까?


답변:


39

$(command)“명령 대체”입니다. 알다시피 command,는을 실행 하고 출력을 캡처 한 다음 $(…); 을 포함하는 명령 행에 삽입합니다 . 예를 들어

$ ls -ld $(date +%B).txt
-rwxr-xr-x  1 Noob Noob    867 Jul  2 11:09 July.txt

${parameter}"매개 변수 대체"입니다. 쉘의 매뉴얼 페이지 인 bash (1) 에서“ Parameter Expansion ”제목 아래에 많은 정보가 있습니다 .

${parameter}
    매개 변수 값 이 대체됩니다. 매개 변수 가 두 자리 이상의 위치 매개 변수이거나 매개 변수 뒤에 이름의 일부로 해석되지 않는 문자가 오는 경우 중괄호가 필요합니다 .

위치 매개 변수에 대해서는 아래의 " 위치 매개 변수 "를 참조하십시오. 다른 답변에서 볼 수 있듯이 가장 일반적인 사용법 parameter은 변수 이름입니다. ${…}위 단락 끝에 언급 된 양식을 사용하면 변수 (예 :)의 값을 가져 와서 문자, 숫자 또는 밑줄로 바로 따라갈 수 있습니다.$variable_name

$ 동물 = 고양이
$ 에코 $ 동물
                                # “동물” 과 같은 변수는 없습니다 .
$ echo $ {animal} s
고양이
$ 에코 $ animal_food
                                # “animal_food” 와 같은 변수는 없습니다 .
$ echo $ {animal} _food
고양이 먹이

따옴표로도이 작업을 수행 할 수 있습니다.

$ echo "$ animal"s
고양이

또는 옵션 연습으로 두 번째 변수를 사용할 수 있습니다.

$ 복수 = s
$ 에코 $ 동물 $ 복수
고양이

그러나 이것은 단지 1 단계입니다. 매뉴얼 페이지의 다음 단락은 약간 비밀 스럽지만 흥미 롭습니다.

매개 변수 의 첫 문자 가 느낌표 ( !) 인 경우 가변 간접 레벨이 도입됩니다. Bash는 나머지 매개 변수에서 형성된 변수의 값을 변수 의 이름으로 사용합니다. 그런 다음이 변수가 확장되고 해당 값은 매개 변수 자체 의 값이 아닌 나머지 대체에 사용 됩니다. 이것을 간접 확장이라고 합니다.     (예외)    느낌표는 간접적으로 도입하기 위해 왼쪽 괄호를 즉시 따라야합니다.

예제를 제외하고 어떻게 이것을 더 명확하게 할 수 있는지 잘 모르겠습니다.

$ 동물 = 고양이
$ 에코 $ 동물
고양이
$ 고양이 = 줄무늬
$ echo $ cat
태비
$ echo $ {! animal}
tabby                            # $ animal  "cat" 이면 $ {! animal}  $ cat입니다 (예 : "tabby").

1½ 단계라고하겠습니다. 2 단계로 수행 할 수있는 흥미로운 작업이 많이 있습니다.

$ 동물 = 고양이
$ echo $ {# animal}
3                                # 끈 길이
$ echo $ {동물 / at / ow}
소                              # 대체

당신은하지 않고 그 일을 수행 할 수 {... }중괄호.

위치 매개 변수

인공적인 예를 고려하십시오 .

$ 고양이 myecho.sh
에코 $ 1 $ 2 $ 3 $ 4 $ 5 $ 6 $ 7 $ 8 $ 9 $ 10 $ 11 $ 12 $ 13 $ 14 $ 15
$ ./myecho.sh 이봐 수수께끼 수수께끼, 고양이와 바이올린, 암소가 달 위로 뛰어 내렸다.
이봐 수수께끼 수수께끼, 고양이와 바이올린, Hey0 Hey1 Hey2 Hey3 Hey4 Hey5

쉘이 이해하지 않기 때문에 $10, $11등이 처리 $10는 것처럼 ${1}0. 그러나 이해 않고 ${10}, ${11}맨 페이지 ( "하나 개 이상의 숫자와 위치 매개 변수")에서 언급 한 바와 같이, 등.

그러나 실제로 그런 스크립트를 작성하지 마십시오. 긴 인수 목록을 처리하는 더 좋은 방법이 있습니다.

위의 내용 (더 많은 형태의 구성 과 함께 )은 쉘 매뉴얼 페이지 인 bash (1) 에서 더 길게 논의됩니다 .${parameter…something_else}

따옴표에 대한 메모

타당한 이유가없는 한 항상 쉘 변수를 인용해야하며 수행중인 작업을 확실히 알고 있어야합니다. 반대로 중괄호는 중요 할 수 있지만 인용 부호만큼 중요하지는 않습니다.

$ filename = "nursery rhyme.txt"
$ ls -ld $ {파일 이름}
ls : 보육원에 액세스 할 수 없음 : 해당 파일 또는 디렉토리가 없습니다.
ls : rhyme.txt에 액세스 할 수 없음 : 해당 파일 또는 디렉토리가 없습니다.
$ ls -ld "$ 파일 이름"
-rwxr-xr-x 1 Noob Noob 5309 Jul 2 11:09 종묘장 rhyme.txt

이는 위치 매개 변수 (예 : 명령 행 인수, 예 :) "$1"및 명령 대체 에도 적용됩니다 .

$ ls -ld $ (날짜 "+ % B % Y"). txt
ls : 7 월에 액세스 할 수 없음 : 해당 파일 또는 디렉토리가 없습니다.
ls : 2015.txt에 액세스 할 수 없음 : 해당 파일 또는 디렉토리가 없습니다.
$ ls -ld "$ (날짜"+ % B % Y "). txt"
-rwxr-xr-x 1 Noob Noob 687 2015 년 7 월 2 일 11 : 09.txt

인용 부호와 … 의 상호 작용에 대한 간략한 논문 은 명령 대체시 이스케이프 처리되지 않은 따옴표를 참조하십시오 .$()


훌륭한 예를 주셔서 감사합니다. 당신은 사용을 정교하게 할 수 있습니까! 귀하의 예에서. 나는 그것이 어떻게 작동하는지 이해하지 못한다.
Noob

@ Noob : 좋아, 나는 사용에 대해 자세히 설명했다 !.
G-Man, 'Reinstate

감사. 어떻게 든! animal은 실제로 cat 값 대신 가변 cat을 참조합니다. echo $ {animal / at / ow}에서 / at가 "c"가되는 방법을 알려주시겠습니까? 이해하기 어렵다.
Noob

또한 "$ {parameter} 매개 변수의 값이 대체됩니다."라는 문구를 자세히 설명 할 수 있습니다. 무엇으로 대체? 매개 변수가 fruit이고 그 값이 apple 인 경우-fruit = apple, $ {fruit}-apple은 ?? 여기서 의미를 대체하지 마십시오
Noob

@Noob :“ ${!animal}실제로 $catcat 값 대신 변수 를 참조합니다 .”그렇습니다. 바로 그 점입니다. "에코 $ {animal / at / ow}에서 / at는 어떻게"c "가됩니까?" / at는 "c"가되지 않습니다. "at"가 "ow"로 바뀌면 "cat"이 "cow"가됩니다.
G-Man은 'Reinstate Monica'라고

7

귀하의 예에서 $ var와 $ {var}는 동일합니다. 그러나 중괄호는 문자열에서 변수를 확장하려는 경우에 유용합니다.

    $ string=foo
    $ echo ${string}bar
      foobar
    $ echo $stringbar

    $ 

따라서 중괄호는 대체 할 새 변수의 이름을 얻기 위해 변수를 대체하는 수단을 제공합니다.


4

나는 보통 문자열에서 더 일반적으로 본다. 이와 같은 것은 작동하지 않습니다.

var="a"
echo "$varRAW_STRING"

그러나 이것은 :

var="a"
echo "${var}RAW_STRING"

올바르게 말했듯 $()이 명령을 실행하는 데 사용됩니다.

dir_contents=$(ls)

백틱을 사용할 수도 있지만 $()더 다재다능합니다. 우선, 백틱은 (쉽게) 중첩 될 수 없습니다.

date_directory=`ls `date '+%Y-%m-%d'`` # Makes no sense
date_directory=$(ls $(date '+%Y-%m-%d')) # Much better

실제로, 백틱 중첩 될 있습니다 : date_directory=`ls \`date '+%Y-%m-%d'\``. 그러나 정말 추악합니다. $(…)훨씬 더 명확하고 사용하기 쉽습니다.
G-Man은 'Reinstate Monica'라고

알았어, 충분 해 그것은 기술적으로 가능하지만, 나는 누구도 단지 때문에 가독성의 그 일을 상상할 수 없다
bytesized

1
음, `…`이었다 전에 년간 명령 치환에 (만) 구문을 발명 한 당신은 아무것도 상상 할 필요가 없습니다 - 사람들이 그것을했다. $(…)
G-Man은 'Reinstate Monica'라고

s / ever it / doing it
more
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.