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

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

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

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

실제로 차이점이 무엇인지 혼란 스럽습니다. '가 주위에 있으면 문자열이라는 뜻이므로 echo는 date날짜를 표시하는 대신 문자 그대로 문자열을 출력할 것이라고 생각했습니다.

답변1

`날짜`date명령의 출력 으로만 확장됩니다 . 그러나 출력에 여러 개의 연속 공백 문자가 있는 경우 불필요한 공백 문자를 제거합니다. (이는 명령 대체가 단어 분리를 수행하고 echo명령이 여러 인수를 처리하는 방식 때문입니다 .)

존재하다"'날짜'", 큰따옴표는 약한 따옴표이므로 변수를 확장하고("$PWD" 시도) 명령 대체를 수행합니다. 확장 결과는 다음과 같습니다.하나의연속 공백을 포함하는 command 에 대한 인수 echo: 즉, 분사는 다음과 같습니다.아니요구현하다.

존재하다''날짜``, 작은따옴표는 더 강력한 따옴표이므로 그 안에 변수 확장이나 명령 대체를 허용하지 않습니다.

인용하다이 링크자세히 알아보세요.

Michael Suelmann이 올바르게 지적한 첫 번째 요점을 편집했습니다.아래 댓글.

답변2

둘 다

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

다음 두 공백은 Nov1로 축소되었습니다(따옴표 제외). 이는 쉘이 공백으로 구분된 각 요소를 구문 분석하고 결과를 6개의 인수로 echo에 보내기 때문입니다. 인용하면 echo는 인수를 받고 인용문은 공백을 유지합니다.

이는 echo 이외의 명령에서 더욱 중요해집니다. 예를 들어, 명령에 foo날짜와 이메일 주소라는 두 개의 매개변수가 필요하다고 가정합니다.

이 경우에는 작동합니다.

foo "`date`" [email protected]

그러나 이는 7개의 매개변수를 전송하여 스크립트를 혼란스럽게 합니다.

foo `date` [email protected]

답변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를 찾고 이러한 패턴과 일치하는 파일 이름 목록으로 확장됩니다. 예를 들어, 의 출력이 (Venus 로케일 및 UVC 시간대에서 자주 발생하며 기본값인 경우 ) 현재 디렉토리에서 중간 이름이 있는 숨겨지지 않은 3자 파일 이름 으로 확장됩니다. , , 의 문자입니다 . 현재 디렉토리의 숨겨지지 않은 모든 하위 디렉토리에 있는 숨겨지지 않은 모든 파일 및 .*?[...]date?%? 33 */*/* UVC 3432$IFS%33UVC3432

그러므로:

  1. 정말로 원하지 않는 한 명령 대체를 항상 큰따옴표로 묶어야 합니다.분사또는파일 이름 생성확장되면 실행됨
  2. 당신이 정말로 원한다면분사$IFS, 분할하려는 문자로 설정해야 합니다 .
  3. 원하는 경우 zsh 외에도분사하지만아니요 파일 이름 생성, 비활성화하려면 set -o noglob(일명 )을 발행해야 합니다 .set -f

작은따옴표는 모든 것을 인용하므로 백틱 문자를 문자 그대로 받아들입니다.

예( -o xtrace무슨 일이 일어나고 있는지 더 쉽게 이해하기 위해 사용):

$ bash --norc -o xtrace
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을 허용할 수 없습니다.

답변4

"날짜"를 사용하면 날짜 출력을 여러 단어로 분할할 수 있습니다. 단어 분할은 명령 대체 후에 수행되기 때문입니다.

"`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`

관련 정보