Schedule
Labs
Assignments
TA office hours
Topic videos
Some course notes
Extra problems
Lecture recordings
An array is normally indexed by integers from 0 to n−1. An "associative array" is instead indexed by an arbitrary string, so it is a general mapping of strings to strings.
In Python, associative arrays are called "dictionaries" and are constructed with brace brackets ('{' and '}').
Sh doesn't have associative arrays -- indeed it doesn't have arrays at all -- but we can produce something basically equivalent to associative arrays with a little trickery. (So this can be used to create arrays indexed by integers, too.)
Suppose we want to do something equivalent to Python's:
x['me'] = 'you'That is to say, the associative array 'x' at index "me" has the value "you".
We will accomplish this by making a compound variable name; the above assignment statement then will look like this:
xme=you
But that's the easy case. Suppose instead we want to do something like
x[y] = 'you'
The following won't quite work:
x$y=youIt's pretty close, but since that line doesn't begin with a word and an equals sign (there's the '$y' there), it's not an assignment statement.
On the other hand, the output from this looks quite fine:
echo x$y=you(it outputs "xme=you"). So how then do we execute that as a statement?
The sh command "eval" reinterprets a line before executing it. This is going to get trickier shortly, but here we just need
eval x$y=youThe variable interpolation is performed, and then the line is re-parsed and executed -- that's what "eval" does.
Now, how do we access this associative array value?
Again, the easy case is if we want to do something like
print x['me']which we can do simply by
echo $xme
The trickier case is to do something like
print x[y]for which we can't do
echo $x$ybecause that just accesses the variables x and y separately.
How do we use eval here? The following is also wrong:
eval echo $x$ybecause it expands $x to whatever is in variable x (maybe nothing), and expands $y to "me", so we just have "eval echo me" which is no different from "echo me" (because there's nothing additional to interpret by interpretating the command-line again before executing).
The key is to realize that we want the two dollar-signs above to be interpreted at different times! We want $y to be expanded to "me" first, then it would be "echo $xme", then we want $xme to be expanded.
What is the output from
echo \$x$y? (answer: "$xme")
So this is what we want interpreted. So the answer is
eval echo \$x$y
Of course we don't have to use the command "echo" here. It can be whatever we want to do with the value. For example, if we wanted to cat the file x[y], we would write
eval cat \$x$y
To make sure you understand this, write a shell script which works like this:
$ sh myscript hello goodbye Assigning "goodbye" to a["hello"] Now a["hello"] is goodbye $But don't just output the above; actually do the variable (array) assignment, so that that "goodbye" which is the last word output above is the value retrieved from the array.
You can assume that there are no spaces or other interesting characters in either of the arguments (it's quite difficult to make this work if there can be interesting characters in either the subscript or the value).
Only after you have this working, you might want to look at my solution.
WARNING ABOUT BACKQUOTES (or '$()'):
Backquotes also subject shell commands to repeated parsing. This causes
problems with the use of backslashes.
If you want to do something like this:
echo I think you should say `eval cat \$filename$greeting` soon.(which won't work)
echo I think you should say `eval cat '$'filename$greeting` soon.