Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I can write

VAR=$VAR1
VAR=${VAR1}
VAR="$VAR1"
VAR="${VAR1}"

the end result to me all seems about the same. Why should I write one or the other? are any of these not portable/POSIX?

share|improve this question
add comment

2 Answers

up vote 21 down vote accepted

VAR=$VAR1 is a simplified version of VAR=${VAR1}. There are things the second can do that the first cant, for instance reference an array index (not portable) or remove a substring (POSIX-portable). See the More on variables section of the Bash Guide for Beginners and Parameter Expansion in the POSIX spec.

Using quotes around a variable as in rm -- "$VAR1" or rm -- "${VAR}" is a good idea. This makes the contents of the variable an atomic unit. If the variable value contains blanks or globbing characters and you don't quote it, then each word is considered for filename generation (globbing) whose expansion makes as many arguments to whatever you're doing.

$ 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

On portability: According to POSIX.1-2008 section 2.6.2, the curly braces are optional.

share|improve this answer
    
@shawn updated my question because I'm also curious about portability –  xenoterracide Dec 16 '10 at 13:46
    
@shawn: I doubt your example is valid. Do you have any real example of a shell where var1=$var expansion gives an error? –  alex Dec 16 '10 at 14:48
    
@alex: Thanks. I thought I had tested that on the command line, but I did it wrong. I changed the example. –  Shawn J. Goff Dec 16 '10 at 15:19
    
With the updated example it's better to keep in mind that you generally should want the quoted version, as the example is rather a corner case. –  alex Dec 16 '10 at 16:15
4  
@Shawn: The quotes are not necessary in an assignment. They are necessary in most other uses, including export VAR=$VAR1. As for the braces, they are optional (check the fourth paragraph of the section you cited; this is the case in all pre-POSIX and POSIX shells). –  Gilles Dec 16 '10 at 19:13
show 1 more comment

${VAR} and $VAR are exactly equivalent. For a plain variable expansion, the only reason to use ${VAR} is when parsing would otherwise grab too many characters into the variable name, as in ${VAR1}_$VAR2 (which without braces would be equivalent to ${VAR1_}$VAR2). Most adorned expansions (${VAR:=default}, ${VAR#prefix}, …) require braces.

In a variable assignment, field splitting (i.e. splitting at whitespace in the value) and pathname expansion (i.e. globbing) are turned off, so VAR=$VAR1 is exactly equivalent to VAR="$VAR1", in all POSIX shells and in all pre-POSIX sh that I've heard of. (POSIX ref: simple commands). For the same reason, VAR=* reliably sets VAR to the literal string *; of course VAR=a b sets VAR to a since the b is a separate word in the first place. There are two other places where the double quotes are unnecessary: redirection targets (>$filename is as good as >"$filename") (only in scripts though, not in most interactive shells) and the word to match in case statements (but not in the pattern).

You do need the double quotes in other cases, in particular in export VAR="${VAR1}" (which can equivalently be written export "VAR=${VAR1}"). The similarity of this case with simple assignments, and the scattered nature of the list of cases where you don't need double quotes, are why I recommend just using double quotes unless you do want to split and glob.

share|improve this answer
1  
As a general rule, I will always quote variable expansions even when I know the value won't contain any IFS characters because I want to be in the habit. The one exception is I don't quote the value when doing a variable assignment (unless required, such as when the value contains a space). This makes editor syntax highlighting more useful when there are command substitutions such as FOO=$(BAR=$(BAZ=blah; printf %s "${BAZ}"); printf %s "${BAR}"). Rather than coloring everything the "string" color, I get syntax highlighting of the nested code. This is also why I avoid backticks. –  Richard Hansen Jan 4 '13 at 19:19
    
While >$file is OK in POSIX scripts, it is not in bash even when non-interactive (unless POSIX compliance is enforced with $POSIXLY_CORRECT or --posix...). –  Stephane Chazelas Jan 23 '13 at 15:01
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.