$ VAR vs $ {VAR} 및 견적 또는 견적


답변:


99

VAR=$VAR1의 단순화 된 버전입니다 VAR=${VAR1}. 예를 들어 배열 인덱스 (휴대용 아님)를 참조하거나 하위 문자열 (POSIX- 포터블)을 제거 할 수없는 경우도 있습니다. POSIX 사양의 초보자 및 매개 변수 확장 을위한 Bash 안내서의 변수에 대한 추가 정보 섹션을 참조하십시오 .

에서 rm -- "$VAR1"와 같이 변수 주위에 따옴표를 사용 rm -- "${VAR}"하는 것이 좋습니다. 변수의 내용을 원자 단위로 만듭니다. 변수 값에 공백 (공백, $IFS특수 변수의 문자 , 기본적으로 공백)이 포함되어 있고 따옴표를 사용하지 않는 경우 각 단어는 파일 이름 생성 (글 로빙)으로 간주되어 확장에 따라 많은 수의 인수가 사용됩니다 하고 있어요

$ find .
.
./*r*
./-rf
./another
./filename
./spaced filename
./another spaced filename
./another spaced filename/x
$ var='spaced filename'
# usually, 'spaced filename' would come from the output of some command and you weren't expecting it
$ rm $var
rm: cannot remove 'spaced': No such file or directory
# oops! I just ran 'rm spaced filename'
$ var='*r*'
$ rm $var
# expands to: 'rm' '-rf' '*r*' 'another spaced filename'

$ find .
.
./another
./spaced filename
./another spaced filename
$ var='another spaced filename'
$ rm -- "$var"
$ find .
.
./another
./spaced filename

이식성 : POSIX.1-2008 섹션 2.6.2 에 따르면 중괄호는 선택 사항입니다.


@shawn은 또한 이식성에 대해 궁금하기 때문에 내 질문을 업데이트했습니다.
xenoterracide

@ shawn : 귀하의 예가 유효한지 의심됩니다. var1=$var확장시 오류가 발생 하는 실제 쉘 예제 가 있습니까?
alex

@ Alex : 감사합니다. 커맨드 라인에서 테스트했다고 생각했지만 잘못했습니다. 예제를 변경했습니다.
Shawn J. Goff

업데이트 된 예제를 사용하는 경우 일반적으로 인용 된 버전을 사용해야한다는 점을 명심해야합니다. 예제는 코너 케이스이기 때문입니다.
alex

9
@Shawn : 과제에 따옴표는 필요 하지 않습니다 . 를 포함하여 대부분의 다른 용도에 필요 export VAR=$VAR1합니다. 중괄호는 선택 사항입니다. 인용 한 섹션의 네 번째 단락을 확인하십시오. 이는 모든 POSIX 이전 및 POSIX 쉘의 경우입니다.
Gilles

60

${VAR}$VAR정확히 동일합니다. 일반 변수 확장의 ${VAR}경우 구문 분석을 수행 할 때와 같이 변수 이름에 너무 많은 문자를 붙일 경우 ${VAR1}_$VAR2(중괄호가없는 것과 동일 함 ${VAR1_}$VAR2) 사용하는 유일한 이유가 있습니다 . 대부분의 장식 확장 ( ${VAR:=default},, ${VAR#prefix}…)에는 중괄호가 필요합니다.

변수 할당에서 필드 분할 (즉, 값에서 공백으로 분할) 및 경로 이름 확장 (예 : 글 로빙)이 해제되어 있으므로 모든 POSIX 셸 및 모든 POSIX 이전 sh에서와 VAR=$VAR1동일합니다 VAR="$VAR1". . (POSIX 참조 : 간단한 명령 ). 같은 이유로 리터럴 문자열로 VAR=*안정적으로 설정 VAR합니다 *. 물론 처음부터 별도의 단어 이므로 VAR=a b설정 VAR합니다 . 말하기 일반적으로 쉘 구문 예를 들어, 하나의 단어를 예상 경우, 큰 따옴표는 필요하지 않습니다 (그러나 패턴에서)하지만, 심지어 거기 당신은 조심해야합니다 예를 들어, POSIX가되도록 지정abcase … in리디렉션 대상 ( >$filename)은 스크립트에서 인용을 요구하지 않지만 bash를 포함한 일부 쉘에는 스크립트에서도 큰 따옴표가 필요합니다. 큰 따옴표는 언제 필요한가요?를 참조하십시오 . 보다 철저한 분석을 위해.

다른 경우, 특히 많은 쉘에서 ( export VAR="${VAR1}"동일하게 작성할 수 있음 export "VAR=${VAR1}") 큰 따옴표가 필요합니다 (POSIX는이 경우를 열어 둡니다). 간단한 할당 으로이 사례의 유사성과 큰 따옴표가 필요하지 않은 사례 목록의 흩어져있는 특성 때문에 분할하고 움켜 쥐고 싶지 않으면 큰 따옴표를 사용하는 것이 좋습니다.


2
일반적으로 IFS습관에 있기 때문에 값에 문자가 포함되어 있지 않다는 것을 알더라도 항상 변수 확장을 인용합니다 . 한 가지 예외는 변수 할당을 수행 할 때 값을 인용하지 않는 것입니다 (예 : 값에 공백이 포함되어있는 경우 제외). 이렇게하면과 같은 명령 대체가있을 때 편집기 구문 강조가 더 유용합니다 FOO=$(BAR=$(BAZ=blah; printf %s "${BAZ}"); printf %s "${BAR}"). 모든 "문자열"색상을 채색하는 대신 중첩 코드의 구문 강조를 얻습니다. 이것이 또한 내가 백틱을 피하는 이유입니다.
Richard Hansen

>$filePOSIX 스크립트에서는 OK 이지만 POSIX 준수가 $POSIXLY_CORRECT또는 --posix... 로 적용되지 않는 한 비대화 식인 경우에도 bash에 없습니다 .
Stéphane Chazelas

에서 인용 부호가 필요하지 않은 것은 사실이지만 VAR=$VAR1, 나는 때때로 local VAR=$VAR1약간의 껍질에서 다른 점에서 다르게 작업하는 것을 기억하는 것에 놀랐습니다 . 그러나 atm, 나는 발산을 재현 할 수 없습니다.
dubiousjim

좋아, 내가 기억하고 있던 문제를 발견 했다 . 일부 껍질에만 나타납니다.
dubiousjim

@dubiousjim local VAR=$VAR1은 마치 export VAR=$VAR1쉘에 따라 다릅니다.
Gilles

8

인용

큰 따옴표는 변수 확장에 사용되고 작은 따옴표는 큰 따옴표, 즉 sans 확장에 사용됩니다.

확장:

this='foo'
that='bar'
these="$this"
those='$that'

산출:

for item in "$this" "$that" "$these" "$those"; do echo "$item"; done
foo
bar
foo
$that

몇 가지 이유로 가능한 경우 인용문을 사용해야한다는 점을 언급하는 것이 좋습니다. 그 중 가장 좋은 방법은 모범 사례로 간주되고 가독성이 뛰어납니다. 또한 Bash는 때로는 기발하고 때로는 비논리적이거나 비합리적이거나 예기치 않은 방식으로 보이기 때문에 인용은 암시 적 기대치를 명시 적으로 변경하여 오류 표면 (또는 잠재적 가능성)을 줄입니다.

인용 하지 않는 것이 합법적 이며 대부분의 경우 작동하지만, 편의상 제공되는 기능이며 이식성이 떨어질 수 있습니다. 의도와 기대를 반영하는 완전한 형식의 관행은 인용하는 것입니다.

치환

이제 구조 "${somevar}"가 대체 조작에 사용 된다는 것도 고려하십시오 . 교체 및 어레이와 같은 여러 사용 사례.

교체 (스트리핑) :

thisfile='foobar.txt.bak'
foo="${thisfile%.*}"   # removes shortest part of value in $thisfile matching after '%' from righthand side
bar="${thisfile%%.*}"  # removes longest matching

for item in "$foo" "$bar"; do echo "$item"; done
foobar.txt
foobar

교체 (교체) :

foobar='Simplest, least effective, least powerful'
# ${var/find/replace_with}
foo="${foobar/least/most}"   #single occurrence
bar="${foobar//least/most}"  #global occurrence (all)

for item in "$foobar" "$foo" "$bar"; do echo "$item"; done
Simplest, least effective, least powerful
Simplest, most effective, least powerful
Simplest, most effective, most powerful

배열 :

mkdir temp
# create files foo.txt, bar.txt, foobar.txt in temp folder
touch temp/{foo,bar,foobar}.txt
# alpha is array of output from ls  
alpha=($(ls temp/*))

echo "$alpha"         #  temp/foo.txt
echo "${alpha}"       #  temp/foo.txt
echo "${alpha[@]}"    #  temp/bar.txt  temp/foobar.txt  temp/foo.txt
echo "${#alpha}"      #  12 # length of first element (implicit index [0])
echo "${#alpha[@]}"   #  3  # number of elements
echo "${alpha[1]}"    #  temp/foobar.txt # second element
echo "${#alpha[1])"   #  15 # length of second element

for item in "${alpha[@]}"; do echo "$item"; done
temp/bar.txt
temp/foobar.txt
temp/foo.txt

이 모든 것이 "${var}"대체 구문 의 표면을 간신히 긁고 있습니다. Bash 쉘 스크립팅에 대한 결정적인 참조는 libre 온라인 참조, TLDP The Linux Documentation Projecthttps://www.tldp.org/LDP/abs/html/parameter-substitution.html


1
매우 유익한.
오리온 엘렌 질

0
ls -la

lrwxrwxrwx.  1 root root      31 Nov 17 13:13 prodhostname
lrwxrwxrwx.  1 root root      33 Nov 17 13:13 testhostname
lrwxrwxrwx.  1 root root      32 Nov 17 13:13 justname

그런 다음 종료하십시오.

env=$1
    if [ ! -f /dirname/${env}hostname ]

curlies를 사용하는 명확한 예로 언급 할 가치가 있습니다.

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