Bash에서 작은 따옴표와 큰 따옴표의 차이점


답변:


579

작은 따옴표는 아무것도 보간하지 않지만 큰 따옴표는 예를 들어 : 변수, 백틱, 특정 \이스케이프 등

예:

$ echo "$(echo "upg")"
upg
$ echo '$(echo "upg")'
$(echo "upg")

Bash 매뉴얼은 다음과 같이 말합니다.

작은 따옴표

작은 따옴표 ( ')로 문자를 묶으면 따옴표 안에 각 문자의 리터럴 값이 유지됩니다. 백 슬래시가 앞에 있어도 작은 따옴표 사이에는 작은 따옴표가 없을 수 있습니다.

3.1.2.3 큰 따옴표

(큰 따옴표 문자를 둘러싸는 것은 ")을 제외하고, 따옴표 내의 모든 문자의 리터럴 값을 보존 $, `, \,와, 역사 확장을 사용하는 경우, !. 문자 $`따옴표 내에서 특별한 의미를 유지합니다 ( 쉘 확장이 ). 다음 문자 중 하나 다음에 할 때 백 슬래시는 특별한 의미를 유지 : $, `, ",\또는 개행. 큰 따옴표 내에서 이러한 문자 중 하나가 뒤에 오는 백 슬래시가 제거됩니다. 특별한 의미가없는 선행 문자 앞에는 백 슬래시가 수정되지 않습니다. 큰 따옴표는 큰 따옴표 안에 백 슬래시를 붙여 따옴표로 묶을 수 있습니다. 사용 가능한 경우 !큰 따옴표 로 표시되는 백 슬래시를 사용하여 이스케이프 하지 않으면 기록 확장이 수행됩니다 . 앞에있는 백 슬래시 !는 제거되지 않습니다.

큰 따옴표로 묶인 경우 특수 매개 변수 *이며 @특별한 의미가 있습니다 ( 쉘 매개 변수 확장 참조 ).


41
"보간"의 의미를 모르는 사람 : en.wikipedia.org/wiki/String_interpolation
Kolob Canyon

당신이 사용하는 경우에 대해 git_prompt사람들이처럼 사용하는 것이 좋습니다 그 자식을 제공 PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ ', 자식 프롬프트 ,이 일 안에 따라. PS#변수에 특별한 것이 있습니까? 보간을하지 않으면 왜 작동합니까?
ekiim

@ekiim 정확한 텍스트가로 변경됩니다 (변경되지 않음) PS1. 시도 echo $PS1무슨 뜻인지 볼 수 있습니다. 그러나 PS1표시되기 전에 평가됩니다 ( PROMPTINGbash 맨 페이지 의 섹션 참조 ). 이것을 테스트하려면을 시도하십시오 PS1='$X'. 프롬프트가 표시되지 않습니다. 그런 다음 실행 X=foo하고 갑자기 프롬프트가 "foo"입니다 ( 표시되는 대신 설정PS1 했을 때 평가되었으므로 여전히 프롬프트가 표시 되지 않습니다).
Adam Batkin

262

허용 대답은 중대하다. 주제를 빠르게 이해하는 데 도움이되는 표를 만들고 있습니다. 설명에는 간단한 변수 a와 색인 배열이 포함 arr됩니다.

설정하면

a=apple      # a simple variable
arr=(apple)  # an indexed array with a single element

다음 echo두 번째 열에서 표현, 우리는 세 번째 열에 표시된 결과 / 동작을 얻을 것입니다. 네 번째 열은 동작을 설명합니다.

 # | Expression  | Result      | Comments
---+-------------+-------------+--------------------------------------------------------------------
 1 | "$a"        | apple       | variables are expanded inside ""
 2 | '$a'        | $a          | variables are not expanded inside ''
 3 | "'$a'"      | 'apple'     | '' has no special meaning inside ""
 4 | '"$a"'      | "$a"        | "" is treated literally inside ''
 5 | '\''        | **invalid** | can not escape a ' within ''; use "'" or $'\'' (ANSI-C quoting)
 6 | "red$arocks"| red         | $arocks does not expand $a; use ${a}rocks to preserve $a
 7 | "redapple$" | redapple$   | $ followed by no variable name evaluates to $
 8 | '\"'        | \"          | \ has no special meaning inside ''
 9 | "\'"        | \'          | \' is interpreted inside "" but has no significance for '
10 | "\""        | "           | \" is interpreted inside ""
11 | "*"         | *           | glob does not work inside "" or ''
12 | "\t\n"      | \t\n        | \t and \n have no special meaning inside "" or ''; use ANSI-C quoting
13 | "`echo hi`" | hi          | `` and $() are evaluated inside ""
14 | '`echo hi`' | `echo hi`   | `` and $() are not evaluated inside ''
15 | '${arr[0]}' | ${arr[0]}   | array access not possible inside ''
16 | "${arr[0]}" | apple       | array access works inside ""
17 | $'$a\''     | $a'         | single quotes can be escaped inside ANSI-C quoting
18 | "$'\t'"     | $'\t'       | ANSI-C quoting is not interpreted inside ""
19 | '!cmd'      | !cmd        | history expansion character '!' is ignored inside ''
20 | "!cmd"      | cmd args    | expands to the most recent command matching "cmd"
21 | $'!cmd'     | !cmd        | history expansion character '!' is ignored inside ANSI-C quotes
---+-------------+-------------+--------------------------------------------------------------------

또한보십시오:


1
받아 들여진 대답은 결국 결과가 The special parameters * and @ have special meaning when in double quotes어떻게 나오는가 ? "*"*
anddero

2
@ Karl-AnderoMere는이 경우 매개 변수로 전혀 확장되지 않기 때문입니다. "$@""$*"매개 변수 확장이다. "@"그리고 "*"아닙니다.
Charles Duffy

@CharlesDuffy 감사합니다. 이제 말이됩니다!
anddero

3
숫자 9 echo "\'"는 나를 반환합니다 \'.
MaxGyver

@MaxGyver : 지적 해 주셔서 감사합니다. 답변을 업데이트했습니다.
codeforester

233

무언가를 반향 할 때 발생하는 상황을 언급하는 경우 작은 따옴표는 문자 사이에있는 것을 문자 그대로 반향하는 반면, 큰 따옴표는 그 사이의 변수를 평가하고 변수의 값을 출력합니다.

예를 들어

#!/bin/sh
MYVAR=sometext
echo "double quotes gives you $MYVAR"
echo 'single quotes gives you $MYVAR'

이것을 줄 것이다 :

double quotes gives you sometext
single quotes gives you $MYVAR

11

다른 사람들은 매우 잘 설명하고 간단한 예를 제시하고 싶습니다.

쉘이 특수 문자를 해석하지 못하도록 텍스트 주위에 작은 따옴표를 사용할 수 있습니다. 작은 따옴표로 묶으면 달러 기호, 공백, 앰퍼샌드, 별표 및 기타 특수 문자가 모두 무시됩니다.

$ echo 'All sorts of things are ignored in single quotes, like $ & * ; |.' 

이것은 이것을 줄 것입니다 :

All sorts of things are ignored in single quotes, like $ & * ; |.

작은 따옴표 안에 넣을 수없는 유일한 것은 작은 따옴표입니다.

따옴표는 따옴표가 여전히 쉘은 달러 기호, 다시 시세 및 백 슬래시를 해석 할 수 제외하고, 작은 따옴표와 유사하게 작동합니다. 백 슬래시는 단일 특수 문자가 해석되는 것을 방지하는 것으로 이미 알려져 있습니다. 변수 대신 달러 기호를 텍스트로 사용해야하는 경우 큰 따옴표 안에 유용 할 수 있습니다. 또한 큰 따옴표를 이스케이프 처리하여 따옴표로 묶은 문자열의 끝으로 해석되지 않습니다.

$ echo "Here's how we can use single ' and double \" quotes within double quotes"

이것은 이것을 줄 것입니다 :

Here's how we can use single ' and double " quotes within double quotes

따옴표로 묶인 문자열의 시작으로 해석되는 아포스트로피는 큰 따옴표 내에서 무시됩니다. 그러나 변수는 큰 따옴표 안에있는 값으로 해석되고 대체됩니다.

$ echo "The current Oracle SID is $ORACLE_SID"

이것은 이것을 줄 것입니다 :

The current Oracle SID is test

역 따옴표 는 전체적으로 작은 따옴표 나 큰 따옴표와 다릅니다. 특수 문자의 해석을 막기 위해 사용되는 대신, 큰 따옴표는 실제로 포함 된 명령을 강제로 실행합니다. 동봉 된 명령이 실행 된 후 출력은 원래 줄의 역 따옴표 대신 대체됩니다. 예를 들어 더 명확해질 것입니다.

$ today=`date '+%A, %B %d, %Y'`
$ echo $today 

이것은 이것을 줄 것입니다 :

Monday, September 28, 2015 

3

의 사용 사이에 명확한 구분이 ' '" ".

' '무엇이든 사용 하면 "변환 또는 번역"이 수행되지 않습니다. 그대로 인쇄됩니다.

을 사용하면 " "주변에 무엇이든지 값으로 "번역되거나 변환됩니다".

번역 / 변환의 의미는 다음과 같습니다. 작은 따옴표 안에있는 것은 그 값으로 "번역"되지 않습니다. 그들은 따옴표 안에있는 그대로 가져갑니다. 예 : a=23그런 다음 표준 출력 echo '$a'을 생성 $a합니다. 반면 표준 출력으로 echo "$a"생산 23됩니다.


1
"번역"또는 "변환"은 무엇을 의미합니까?
니코 하세

이 답변은 매우 혼란스럽고 기존의 좋은 답변 위에 아무것도 추가하지 않습니다.
codeforester

2
이것은 내가 이해하기 쉬운 과도하지 않은 내 의견으로는 짧은 간결한 대답이었습니다. 번역 / 변환을 말할 때 큰 따옴표는 작은 따옴표가 변수를 확장하지 않는 변수를 확장한다는 의미입니다.
B_e_n_n_y_

1
예, 이것이 가장 좋은 답변입니다. 이것이 정답입니다.
Jamey Kirby

3

이것은에서 인용 부호를 다룰 때 사실상의 대답이므로 bash쉘에서 산술 연산자를 다룰 때 위의 대답에서 놓친 점을 하나 더 추가합니다.

bash쉘은 두 가지 연산을 지원하는 하나에 의해 정의 내장 let명령 및 $((..))연산자. 전자는 산술 표현식을 평가하는 반면 후자는 좀 더 복합적인 진술입니다.

함께 사용되는 산술 연산 식은 let다른 쉘 명령과 마찬가지로 단어 분할, 경로 이름 확장 을 거치는 것으로 이해해야 합니다. 따라서 적절한 인용 및 탈출이 필요합니다.

사용할 때이 예제를 참조하십시오 let

let 'foo = 2 + 1'
echo $foo
3

여기에 작은 따옴표를 사용하면 변수 확장이 필요하지 않으므로 여기에서 절대 인용 부호를 사용하는 것이 좋습니다.

bar=1
let 'foo = $bar + 1'

$bar아래 작은 따옴표는 확장 되지 않고 다음 과 같이 큰 따옴표로 묶어야 하므로 비참하게 실패 합니다.

let 'foo = '"$bar"' + 1'

이것은 이유 중 하나 $((..))여야하며을 항상 과도하게 사용해야합니다 let. 내용물이 단어를 쪼개지 않기 때문입니다. 사용하는 이전 예제 let는 다음과 같이 간단하게 작성할 수 있습니다.

(( bar=1, foo = bar + 1 ))

항상 $((..))작은 따옴표없이 사용하십시오

$((..))큰 따옴표와 함께 사용할 수 있지만 그 결과 큰 따옴표가 필요한 내용을 포함 할 없으므로 목적이 없습니다 . 작은 따옴표가 아닌지 확인하십시오.

printf '%d\n' '$((1+1))'
-bash: printf: $((1+1)): invalid number
printf '%d\n' $((1+1))
2
printf '%d\n' "$((1+1))"
2

$((..))작은 따옴표로 묶은 문자열 내 에서 연산자 를 사용하는 특별한 경우가있을 수 있습니다 . 연산자가 따옴표가 없거나 큰 따옴표로 묶는 방식으로 따옴표를 보간해야합니다. 예를 들어 curl, 요청이 이루어질 때마다 카운터 내에서 연산자를 사용하여 카운터를 전달 하려는 경우를 고려하십시오.

curl http://myurl.com --data-binary '{"requestCounter":'"$((reqcnt++))"'}'

리터럴 문자열 $((reqcnt++))requestCounter필드 로 전달 되지 않고 중첩 된 큰 따옴표를 사용하십시오 .


2
찰스 더피 (Charles Duffy) 는 큰 따옴표 로도 여기 에 좋은 사례 제시 $((...))합니다. 그것은 "조금"편집증일지도 모르지만 IFS=0예를 들어 가질 가능성은 적지 만 확실히 불가능하지는 않습니다 :)
PesaThe

레거시 $[[...]]구문도 있지만 잊어 버린 것일 수도 있습니다.
tripleee
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.