Reputation: 10892
I just want to declare a few variable names on a single line. These names should be visible as names which have been taken, even if not necessarily set to a specific value.
In C
, I would do this:
int i, j, k;
In Bash
, I am welcomed to a world of astonishment:
declare -a a1 a2 a3; echo ${!a*}
outputs:
a1 a2 a3
Works! :) But these are arrays so presumably they are created empty.. not the right example.
Let's try again. This:
declare -r b1 b2 b3; echo ${!b*}
outputs:
<nothing>
but now:
b1=foo
bombs with:
bash: b1: readonly variable
Odd.
It marks the name as read-only but the name itself is not seen by ${!...}
indirection.
Makes me wanna tell Bash
"make up your mind! do you know of these symbols or not?"
Anyway, surely this will work:
declare -g c1 c2 c3; echo ${!c*}
outputs:
<nothing>
Finally:
declare -x d1 d2 d3; echo ${!d}
outputs:
<nothing>
What is puzzling is that:
declare -p
sees all defined variables but they are only printed by ${!...}
calls if they have been assigned a value. But the man
page does not say: "those names which have a value will be expanded..". Strange.
So I concluded that this would not work to declare my variable names, as I originally intended and is my objective anyway, because I am not assigning a value:
declare y1= y2= y3=; echo ${!y*}
... but, to my dismay, this yields:
y1 y2 y3
So the question becomes:
Which values have y1, y2, y3 after declare y1= y2= y3=
?
I have tried to answer myself, because if the are finally seen as available names, these variables must have something in them. Even, possibly, the \0
value. Should they not, none of the above would make sense, right?
printf "$v1" > /tmp/tmp
gives this:
hexdump -C /tmp/tmp
<nothing>
and:
wc -c /tmp/tmp
gives:
0 /tmp/tmp
File completely empty.
Anybody understands this? All I wanted to do, was a C
-like int i, j, k;
..
I need it because in my functions I very reasonably check some user and environment conditions by checking whether some variables are "visible". Based on that, the script does something and updates these status-signalling variables. It is inconsistent that something that should go into the symbol table, and appear in declare -p independently of having a value or not, would appear in variable name expansion only if it has a value.. with the exception of setting a value, completely empty, which makes the name visible again. Clearly I cannot rely on a consistent behaviour here?
Upvotes: 0
Views: 65
Reputation: 200493
So the question becomes:
Which values have y1, y2, y3 after
declare y1= y2= y3=
?
The answer to your question lies in declare -p
:
cobalt@carbon:~ $ declare foo
cobalt@carbon:~ $ declare -p | grep -- "-- foo"
declare -- foo
cobalt@carbon:~ $ declare foo=
cobalt@carbon:~ $ declare -p | grep -- "-- foo"
declare -- foo=""
cobalt@carbon:~ $ declare -a foo
cobalt@carbon:~ $ declare -p | grep foo
declare -a foo='([0]="")'
${!prefix*}
apparently expands only names of variables that have been declared with a value assigned to them. A simple declaration does not assign a value, regardless of whether the variable is exported (-x
) or declared global (-g
). Declaration of array variables (declare -a var
), however, is different, because it does assign a value. The same goes for declaration with explicit assignment of a value (declare var=
).
Upvotes: 1