10
$ a='"apple","ball","cat"'
$ a='['$a
$ echo $a
["apple","ball","cat"
$ a=$a']'
$ echo $a
b

I'm stumped hard by the result b while I expect to see ["apple,"ball","cat"]. What am I missing here?

This is from bash shell on Mac. Also see it on CentOS 7, while not on Fedora. Can someone please explain?

John Kugelman
  • 2,037
  • 2
  • 16
  • 23
user3866672
  • 119
  • 5

2 Answers2

27

There is a file with the name b in the current directory.

[...]

is a pattern matching expression. It matches every file of which the name consists of a single letter between [ and ].

This is similar to having * in a variable value and using the variable without quotes.

Hauke Laging
  • 88,146
  • 18
  • 125
  • 174
  • 2
    +1 Good catch. The corollary here is, I suppose, that variables should be quoted when used (`echo "$a"` writes the literal value of `$a`). – roaima Nov 14 '17 at 23:38
  • 6
    For loads more information about that: [Security implications of forgetting to quote a variable in bash/POSIX shells](https://unix.stackexchange.com/q/171346/4667) – glenn jackman Nov 15 '17 at 00:15
3

Hauke already answered why it's happening. For future reference, you can also troubleshoot what is happening with strace:

$ touch a b l
$ a='["apple","ball"]'                                                      
$ strace -e trace=execve echo $a
execve("/bin/echo", ["echo", "a", "b", "l"], [/* 82 vars */]) = 0
a b l
+++ exited with 0 +++

Or with set -x:

$ set -x; echo $a
+ set -x
+ echo a b l
a b l

It's might not immediately be clear, but at least you see that shell has converted the unquoted variable into a list of items; from there we can deduce that filename expansion occurred.

Sergiy Kolodyazhnyy
  • 16,187
  • 11
  • 53
  • 104