echo`date`, echo“`date`”및 echo '`date`'의 차이점은 무엇입니까?


23

이 세 명령의 차이점은 무엇입니까?

echo `date`
echo "`date`"
echo '`date`'

차이점이 실제로 무엇인지 혼란 스럽습니다. 나는 '가 그 주위에있을 때 그것이 문자열이라는 것을 의미한다고 생각합니다. 따라서 echo는 date날짜를 표시하는 대신 문자 그대로 문자열을 출력 합니까?

답변:


19

`date`date명령 의 출력으로 확장됩니다 . 그러나 출력에 연속 공백 문자가 두 개 이상있는 위치에서 여분의 공백 문자가 제거됩니다. (이는 명령 대체가 단어 분할에 종속되고 echo명령이 여러 인수를 처리 하는 방식 때문입니다 .)

에서 "`date`" 그들이 변수를 확장 ( "$ PWD"를 시도) 및 명령 대체를 수행 할 수 있도록, 따옴표는 약한 따옴표입니다. 확장 결과는 연속 된 공백을 포함 하여 명령에 단일 인수로 전달됩니다 echo. 즉, 단어 분할이 수행 되지 않습니다 .

에서 '`date`' 그들이 내에서 변수 나 명령 치환의 확장을 허용하지 않도록, 작은 따옴표는, 강한 따옴표입니다.

자세한 설명은 이 링크 를 참조하십시오 .

아래 주석 에서 Michael Suelmann이 올바르게 지적한대로 첫 번째 점을 편집했습니다 .


1
날짜와 관련된 문자는 정확히 무엇입니까? 올바르게 이해하면 작은 따옴표로 메타 문자가 작동하지 않습니까?
John

올바르게 이해하면 작은 따옴표로 메타 문자가 작동하지 않습니까?
John

8
`는 종종이 시나리오와 다양한 유닉스 문서 / 책에서 "백틱"이라고 불립니다. 실제로는 심볼의 이름이더라도 그 자체로는 유니 코드 중력 악센트로 사용되지 않습니다. 그리고 작은 따옴표로 묶으면 메타 문자 / 표현이 확장되지 않는 것이 맞습니다.
Jim Stewart

날짜 나 로케일에 따라 결과가 약간 다를 수 있으므로 첫 번째 설명이 올바르지 않습니다. 두 번째 명령 만 베어 date명령 과 동일한 내용을 출력합니다 .
jlliagre

1
"11월"과 "1"사이의 여분의 공간뿐만 아니라 HTML에서 제거 @BonsiScott)
Izkata

16

양자 모두

echo `date`

echo "`date`"

날짜가 표시됩니다. 후자의 출력은 date자체 실행의 출력과 같습니다 .

그러나 차이 가 있습니다. "따옴표로 묶은 것은 단일 인수로 "전송됩니다 echo. 따옴표는 전체 명령의 출력을 하나의 인수로 캡슐화합니다. 그 echo사이에 공백이있는 순서대로 인수를 인쇄하기 때문에 기본적으로 동일하게 보입니다.

미묘한 차이의 예는 다음과 같습니다.

echo `date`

생산 :

Fri Nov 1 01:48:45 EST 2013

그러나:

echo "`date`"

생산 :

Fri Nov  1 01:48:49 EST 2013

이후의 두 공백 Nov은 따옴표없이 하나로 줄어 듭니다. 쉘이 공백으로 구분 된 각 요소를 구문 분석하고 결과를 6 개의 인수로 에코에 보내기 때문입니다. 인용하면 echo는 하나의 인수를 받고 인용 부호는 공백을 유지합니다.

이것은 echo 이외의 명령에서 훨씬 더 중요해집니다. 예를 들어, foo날짜와 이메일 주소라는 두 가지 인수를 원하는 명령 을 상상해보십시오 .

이것은 해당 시나리오에서 작동합니다.

foo "`date`" joeuser@example.com

그러나 이것은 7 개의 인수를 보내서 스크립트를 혼란스럽게합니다.

foo `date` joeuser@example.com

3
당신은 첫 문장에서 자기 모순입니다. 첫 번째와 두 번째 양식이 나중에 설명 할 때 항상 같은 내용을 출력하지는 않습니다.
jlliagre

감사. 더 명확하게 표현하기 위해 문구를 변경했습니다.
짐 스튜어트

3

POSIX 쉘 `date`에서 고대 형태의 명령 대체입니다. 현대 구문은 $(date)입니다.

두 경우 모두 date후행 줄 바꿈 문자를 제거 하여 출력으로 확장합니다 (출력에 NUL 문자가 포함되어 있지 않은 경우).

그러나 큰 따옴표 안에 있지 않고 목록 컨텍스트에없는 경우 (예를 들어 echo귀하의 경우 와 같은 간단한 명령에 대한 인수 ) 해당 확장에는 다음이 추가로 적용됩니다.

  1. 단어 분리 : 즉, " date마지막 줄 바꿈 문자가 제거 된 결과"$IFS변수 의 현재 값 (기본적으로 공백, 탭 및 줄 바꿈 (및 NUL 포함 zsh))에 따라 여러 단어 로 분할됩니다 .

    예를 들어, 영어 로케일과 영국 본토 시간대에서 자주 date출력되는 Fri 1 Nov 14:11:15 GMT 2013\n것과 같이 출력이 $IFS현재 포함되어있는 :경우 3 단어 : Fri 1 Nov 14, 11및 로 나뉩니다 15 GMT 2013.

  2. 파일 이름 생성 (일명 글 로빙 (제외) zsh) : (즉, 위의 분할로 인한 각 단어는 와일드 카드 문자를보고있다 *, ?, [...]약간의 껍질을 더 가지고 있지만), 그 패턴과 일치하는 파일 이름 목록에 확장했다. 예를 들어,의 출력이있는 경우 date입니다 ?%? 33 */*/* UVC 3432(종종 금성 로케일과 UVC 시간대에 같은), 그리고 $IFS) 기본값입니다, 그 모든 팽창 비 숨겨진 그 중간 문자 현재 디렉토리에 3 문자 파일 이름 %, 33, 모든 숨겨지지 않은 현재 디렉토리의 하위 디렉토리의 모든 숨겨지지 않은 하위 디렉토리에있는 모든 비 숨김 파일 UVC3432.

그 이유는 다음과 같습니다.

  1. 단어 분할 또는 파일 이름 생성 시 확장을 수행 하지 않으려면 항상 명령 대체를 따옴표로 묶어야합니다 (큰 따옴표 사용).
  2. 당신이 원하는 할 경우 단어 분할을 , 당신은 설정해야합니다 $IFS당신이 분할하려는 자.
  3. 파일 이름 생성이 아닌 단어 분리를 원할 경우 a 를 실행하여 비활성화하십시오.set +f

작은 따옴표는 모든 것을 인용하므로 백틱 문자가 문자 그대로 사용됩니다.

예를 사용 -x하면 진행 상황을 쉽게 볼 수 있습니다.

$ bash --norc -x
bash-4.2$ IFS=:
+ IFS=:
bash-4.2$ echo `date`
++ date
+ echo 'Fri  1 Nov 14' 42 '33 GMT 2013'
Fri  1 Nov 14 42 33 GMT 2013
bash-4.2$ echo "`date`"
++ date
+ echo 'Fri  1 Nov 14:42:41 GMT 2013'
Fri  1 Nov 14:42:41 GMT 2013

bash-4.2$ cd /lib/modules
+ cd /lib/modules
bash-4.2$ export TZ=UVC LC_ALL=vs_VS
+ export TZ=UVC LC_ALL=vs_VS
+ TZ=UVC
+ LC_ALL=vs_VS
bash-4.2$ unset -v IFS     # get the default behaviour
+ unset -v IFS
bash-4.2$ echo `date`
++ date
+ echo '?%?' 33 3.10-2-amd64/build/arch 3.10-2-amd64/build/include 3.10-2-amd64/build/Makefile 3.10-2-amd64/build/Module.symvers 3.10-2-amd64/build/scripts 3.10-2-amd64/kernel/arch 3.10-2-amd64/kernel/crypto 3.10-2-amd64/kernel/drivers 3.10-2-amd64/kernel/fs 3.10-2-amd64/kernel/lib 3.10-2-amd64/kernel/mm 3.10-2-amd64/kernel/net 3.10-2-amd64/kernel/sound 3.10-2-amd64/source/arch 3.10-2-amd64/source/include 3.10-2-amd64/source/Makefile 3.10-2-amd64/source/scripts 3.10-2-amd64/updates/dkms 3.10-3-amd64/build/arch 3.10-3-amd64/build/include 3.10-3-amd64/build/Makefile 3.10-3-amd64/build/Module.symvers 3.10-3-amd64/build/scripts 3.10-3-amd64/kernel/arch 3.10-3-amd64/kernel/crypto 3.10-3-amd64/kernel/drivers 3.10-3-amd64/kernel/fs 3.10-3-amd64/kernel/lib 3.10-3-amd64/kernel/mm 3.10-3-amd64/kernel/net 3.10-3-amd64/kernel/sound 3.10-3-amd64/source/arch 3.10-3-amd64/source/include 3.10-3-amd64/source/Makefile 3.10-3-amd64/source/scripts 3.10-3-amd64/updates/dkms UVC 3432
?%? 33 3.10-2-amd64/build/arch 3.10-2-amd64/build/include 3.10-2-amd64/build/Makefile 3.10-2-amd64/build/Module.symvers 3.10-2-amd64/build/scripts 3.10-2-amd64/kernel/arch 3.10-2-amd64/kernel/crypto 3.10-2-amd64/kernel/drivers 3.10-2-amd64/kernel/fs 3.10-2-amd64/kernel/lib 3.10-2-amd64/kernel/mm 3.10-2-amd64/kernel/net 3.10-2-amd64/kernel/sound 3.10-2-amd64/source/arch 3.10-2-amd64/source/include 3.10-2-amd64/source/Makefile 3.10-2-amd64/source/scripts 3.10-2-amd64/updates/dkms 3.10-3-amd64/build/arch 3.10-3-amd64/build/include 3.10-3-amd64/build/Makefile 3.10-3-amd64/build/Module.symvers 3.10-3-amd64/build/scripts 3.10-3-amd64/kernel/arch 3.10-3-amd64/kernel/crypto 3.10-3-amd64/kernel/drivers 3.10-3-amd64/kernel/fs 3.10-3-amd64/kernel/lib 3.10-3-amd64/kernel/mm 3.10-3-amd64/kernel/net 3.10-3-amd64/kernel/sound 3.10-3-amd64/source/arch 3.10-3-amd64/source/include 3.10-3-amd64/source/Makefile 3.10-3-amd64/source/scripts 3.10-3-amd64/updates/dkms UVC 3432
bash-4.2$ echo "`date`"
++ date
+ echo '?%? 33 */*/* UVC 3432'
?%? 33 */*/* UVC 3432

출력에 NUL 문자가 포함 된 경우 동작은 쉘마다 다릅니다. 일부는 제거하고 일부는 첫 번째 NUL 문자에서 출력을 자르고 zsh유지하지만 외부 명령은 NUL을 포함하는 인수를 사용할 수 없습니다.


실제 "POSIX 쉘"과 같은 것은 없습니다. 기능의 제한된 서브 세트를 사용하여 다양한 관련 POSIX 표준을 준수 할 수있는 쉘이 있습니다.
fpmurphy

0

`date`를 사용하면 명령 대체 후에 단어 분할이 수행되므로 날짜 출력이 여러 단어로 분할됩니다.

"`date`"를 사용하면 큰 따옴표 사이에 명령 대체가 있기 때문에 날짜 출력을 하나의 단어 / 매개 변수로 얻을 수 있지만 출력은 더 이상 구문 분석되지 않습니다. 아래 예에서 "$ i"와 같은 변수 확장에서도 마찬가지입니다.

'`date'를 사용하면 작은 따옴표 사이에 명령 대체가 없으므로 리터럴`date`가 표시됩니다.

아마도 세 가지 형식의 차이점이 다음과 같이 더 잘 보일 것입니다.

> for i in `date`; do echo "$i"; done
Fr
1.
Nov
12:25:30
CET
2013

> for i in "`date`"; do echo "$i"; done
Fr 1. Nov 12:25:38 CET 2013

> for i in '`date`'; do echo "$i"; done
`date`
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.