따옴표로 변수를 정의하는 경우:
TEMP="~/Dropbox"
그 다음에
ls $TEMP
작동하지 않습니다. 대신
echo $TEMP | ls
일하다.
동일한 결과를 얻으려면 다음과 같이 따옴표 없이 변수를 정의할 수도 있습니다.
TEMP=~/Dropbox
이렇게 하면 간단히 입력할 수 있습니다.
ls $TEMP
나는 그들 사이의 차이점에 대해 혼란스럽고 언제 어디서 이 두 정의를 각각 사용해야 하는지 알고 싶습니다.
답변1
TEMP="~/Dropbox"
위의 내용은 리터럴 물결표와 슬래시가 포함된 변수를 정의합니다. 따옴표로 묶여 있기 때문에 쉘은 ~/
홈 디렉토리로 확장되지 않습니다. 관찰하다:
$ echo "quotes=~/" noquotes=~/
quotes=~/ noquotes=/home/john1024/
~/
따라서 홈 디렉토리를 나타내 려면 ~/
따옴표를 벗어나야 합니다. 다음은 작동합니다:
TEMP=~/"Dropbox"
~/
따옴표로 묶으면 어떻게 되는지 생각해 봅시다 :
TEMP="~/Dropbox"
ls $TEMP
~/Dropbox
위의 명령은 이름이 지정된 디렉터리에 있는 파일을 나타내는 파일을 찾습니다 . 이름이 지정된 디렉터리가 없을 가능성이 높으므로 "해당 파일이나 디렉터리가 없습니다."라는 오류 메시지가 반환됩니다.Dropbox
~
~
ls
또한 아래 명령은 생각한 대로 작동하지 않습니다.
echo $TEMP | ls
ls
표준 입력은 무시됩니다. bare ls
명령은 해당 디렉터리가 무엇이든 현재 디렉터리의 파일만 나열합니다.
답변2
man bash하고 "물결표 확장"을 찾으십시오.
즉, 따옴표가 없는 물결표(~)는 사용자의 집으로 대체되며, 변수의 일부인 경우 더 이상 발생하지 않습니다.
$ T=~/Downloads
$ echo $T
/home/zstegi/Downloads
$ T="~/Downloads"
$ echo $T
~/Downloads
답변3
이 문제에는 여러 측면이 있습니다. 첫째, 인용된 대입문의 효과는 다음 두 가지 이유로 인용문이 없는 동일한 대입문과 다를 수 있습니다.
과제에 구분 기호가 포함된 경우통사론토큰(예:
;<>
또는 공백)그런 다음 따옴표로 묶을 수 있으며, 따옴표가 없는 할당문은 마커로 구분됩니다.및 일부 다른 셸 에서
bash
토큰은 배열 할당을 나타내는()
데 사용되는 특수한 경우이지만var=(...)
배열 확장을 지원하지 않는 POSIX 셸에서는 동일한 구성이 따옴표 없이 구문 오류가 됩니다.( spc= sc=; echo "<$spc>:<$sc>" spc=' ' sc=\;; echo "<$spc>:<$sc>" )
<>:<> < >:<;>
할당에 확장 표시가 포함된 경우 따옴표로 인해 확장이 발생하지 않을 수 있으며, 확장 표시가 없으면 확장이 발생할 수 있습니다.
- 포함된 모든 토큰이내에확장 내용이 실제로 확장에서 할당된 변수로 전달되기 때문에 확장이 적용되지 않습니다.
큰따옴표는 표현식의 쉘 확장
"
에 사용할 수 없으므로 일반적으로 대입문에서는 부적합합니다. 단, 다음을 포함하는 표현식의 확장$
에는 사용할 수 있습니다.$
그리고컨텍스트의 다른 쉘 태그에 대한 참조입니다.( spc=\ sc=";" tkns=$(printf "(<\n\'\t)>|")$spc$sc\" names=tkns$spc$"sc$spc$"spc printf ::$%s::\\n "$names" "$tkns" )
::$tkns $sc $spc:: ::$(< \' )>| ;"::
셸 토큰은 셸에서 매우 특수한 문자입니다. 이는 명령을 서로 구분하고 명령 단어에서 명령 인수까지 구분하는 문자입니다. 쉘 단어를 분리/결합하는 문자입니다. 쉘 태그는 쉘 문자입니다.통사론파서(또는어휘 분석기)쉘은 명령의 일부 확장을 고려할 기회를 갖기 전에 명령을 읽으면서 해당 작업을 찾아 수행합니다.
하지만 다른 캐릭터도 있어요거의껍질에 특별합니다. 이는 셸 매개변수 값에 포함된 문자와 같이 셸 확장에 영향을 주는 문자 $IFS
는 물론, ?[*
질문에서 언급한 대로 ~
물결표와 같은 파일 이름 확장 메타 문자입니다.
특수한 경우 물결표를 제외하고 ~
이러한 문자는 할당문과 아무 관련이 없습니다.일문맥(대목록문맥)$IFS
분할 및 파일 이름 확장자의 영향 을 받지 않습니다 . 따라서 변수 할당에서 발생하는 확장에는 명령 목록에서와 같이 리터럴 값 보호가 필요하지 않습니다.
그래서 다음은 작동합니다 ...
(meta=*?; meta=[$meta; echo "$meta")
[*?
그러나 물결표는 ~
특별한 쉘 확장입니다. 확장 처리 alias
는 내용이 항상 문자 그대로 확장된다는 점에서 매우 쉘과 유사합니다 . ~
물결표와 확장 모두 - 확장을 나타내는 alias
일반적인 달러 기호와 같습니다.$
일상황 - 예언제나파일 이름 확장자의 영향을 받지 않습니다 $IFS
. 그러나 ~
물결표는 거의 항상 인수로 확장되며 값이 <space>로 끝나는 다른 확장된 쉘 alias
바로 뒤에 나오지 않는 한 쉘은 해당 컨텍스트에서 확장될 수 없다는 점에서 다릅니다 .alias
물결표 확장은 ~
어떤 종류의 따옴표 안에서도 발생하지 않으며, 모든 측면에서 적절하게 구분되지 않거나 후행 컨텍스트 이름이 시스템 사용자와 쉘에서 이 사실을 제대로 인식할 수 없는 한 전혀 발생하지 않습니다.
그래서...
~some_user
...사용자의 홈 디렉토리로 확장됩니다.some_user
쉘이 그러한 사용자가 존재한다는 것을 확인할 수 있으면 그렇지 않으면 전혀 확장되지 않습니다.
도착하다올바르게 정의됨물결표 확장의 경우 오른쪽에 있는 ~
따옴표와 a를 제외하고 이미 언급한 쉘 태그 중 하나를 사용할 수 있습니다./
목록맥락에서 또는일컨텍스트는 /
오른쪽 :
이나 왼쪽, =
할당문의 첫 번째 또는 :
다른 어느 곳에나 있습니다.
후행 컨텍스트가 없고 ~
물결표가 적절하게 구분된 경우 ~
물결표는 쉘 변수의 현재 값으로 확장됩니다 $HOME
. 이러한 구별은 물결표 확장을 논의할 때 종종 실수로 무시됩니다 ~
. 쉘 변수는 다른 시간과 마찬가지로 언제든지 재할당하거나 재할당할 수 있으므로 사용자의 홈 디렉터리와 값이 $HOME
동일할 필요는 없습니다. 실제로 언제$HOME
unset
$HOME
예 unset
~
, POSIX는 별도의 물결표 확장 동작을 유지합니다.명시되지 않은그러나 bash
예를 들어 시스템에서 현재 사용자의 홈 디렉터리를 찾으려는 시도가 이루어집니다.
예를 들어:
HOME="
:~"::~//~ bash -c '
printf "\t<%s>" ~/ ~mikeserv/
HOME=; echo
printf "\t<%s>" ~/ ~mikeserv/
unset HOME; echo
printf "\t<%s>" ~/ ~mikeserv/
'
<
:~::/home/mikeserv//~/> </home/mikeserv/>
</> </home/mikeserv/>
</home/mikeserv/> </home/mikeserv/>