5

This question is about assigning the entire contents of one variable to another variable.

Variable is not being used (sent to echo, etc.)

No parameter expansion is being done during the assignment.

My question also pertains only to POSIX shell (no arrays being used here).

error="You have an error in your input"

newVar="$error"
# vs.
newVar=$error
#         ↑
#         └─This assignment is the question. It doesn't seem that quotes are
#           needed here in order to assign the entire contents of $error to
#           a new variable.

#                 ┌─(But quotes are required when they're used.)
#                 ↓
printf "%s\n" "$error"
# => You have an error in your input
printf "%s\n" "$newVar"
# => You have an error in your input

Are there any gotchas I'm missing in just writing newVar=$error?

Update:

Regardless of what's in $error, I want to know will that same data carry over into $newVar without throwing any errors or mangling the data.

$ error="Test * ${1} \n [!a] [[:punct:]] ./test \t \n \\"
$ newVar=$error
#       ↑
#       └─Does this step ever fail or cause the two variables to differ?
$ echo "$error"
Test *  \n [!a] [[:punct:]] ./test \t \n \
$ echo "$newVar"
Test *  \n [!a] [[:punct:]] ./test \t \n \
  • 2
    You can refer to this. – cuonglm Aug 05 '15 at 16:39
  • tangentially, you may be misunderstanding the action of printf -- if you give it one "Argument no matter how many spaces, in quotes" then it will print the formatted values only once. If you instead give printf an unquoted variable with spaces in it, then it will repeat the format string for each. – Jeff Schaller Aug 05 '15 at 16:41
  • If you're going to play with edge cases, you should probably stick to printf "%s\n" "$var", because echo "$var" is less predictable/reliable when $var begins with dash (-) or contains backslash (\).  (And of course printf "$var" is unforgiving if $var contains percent (%) or backslash (\).) – G-Man Says 'Reinstate Monica' Aug 05 '15 at 19:21
  • 2
    @EvgenyVereshchagin No, that question only touches this subject in passing. http://unix.stackexchange.com/questions/68694/when-is-double-quoting-necessary might be considered a duplicate. – Gilles 'SO- stop being evil' Aug 05 '15 at 22:36

1 Answers1

12

In Bourne-like shells (if we forget about bugs1 in some old implementations of some shells)

var=$otherVar

is fine. You're assigning to a scalar variable, so there can't be glob+splitting here, so you don't need to write it var="$otherVar" (though the quotes don't harm here).

An exception is for:

var=$*

and:

var=$@

You should only use var="$*". The behaviour of var=$@ var=$* var="$@" varies among shells when the first character of $IFS is not space.

Of course, in:

array=("$var")

You do need the quotes, as otherwise, the array elements would be assigned the result of the split+globbing of $var.

Also note that you need the quotes in:

export var="$otherVar"

with many shells (in them, here, it's a simple command, so split+glob occurs).

And in:

env var="$otherVar" cmd

Or

awk -v var="$otherVar"...

If in doubt, use the quotes.


1 Some old versions of zsh had an issue with backslash in front of wildcard characters when in sh emulation:

$ (a='\*' exec -a sh zsh-3.1.9 -c 'b=$a; printf "%s\n" "$b"')
*
$ (a='\*' exec -a sh zsh-3.1.9 -c 'b="$a"; printf "%s\n" "$b"')
\*

That was fixed a long time ago.