[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: setting array values
From: |
Chet Ramey |
Subject: |
Re: setting array values |
Date: |
Mon, 10 Dec 2001 10:29:40 -0500 |
> Machine Type: hppa1.1-hp-hpux10.20
>
> Bash Version: 2.05
> Patch Level: 0
> Release Status: release
>
> Description:
> I'm having problems getting array variables assigned, albeit in an
> obscure way :-) Since bash's definition of "POSIX conformant" doesn't
> match HP's definition, I'm trying to define a function to hide the difference.
Since POSIX.2 doesn't have anything to say about arrays, the differences
between ksh88 and bash don't really matter for posix conformance.
> So both the array name and the values have to be variables, and I can't get
> bash to cooperate. The minimal problem is shown in two ways in the repeat
> by section below. (For now I'll skip the function, but IMHO the below should
> work :-)
I think you'll find that `eval' and quoting are your friends here.
> bash-2.05$ declare -a a=(1 2 3)
> bash-2.05$ echo ${a[*]}
> 1 2 3
This works OK.
> bash-2.05$ set 3 4 5
> bash-2.05$ declare -a a=($*)
> bash-2.05$ echo ${a[*]}
> 3 4 5
This does, too.
> bash-2.05$ foo=a
> bash-2.05$ declare -a $foo=(6 7 8)
> bash-2.05$ echo ${a[*]}
> 6 7 8
This works only by chance, mostly because the parser is too lenient
and the `(6 7 8)', not being the results of an expansion, doesn't get
split.
The parser tries to be helpful and reads the whole argument as a
single word. It probably shouldn't do this; the `$foo=(6 7 8)' is not
a valid assignment statement. Since it's not an assignment statement,
the heuristics that inhibit word splitting for arguments to
`assignment builtins' (typeset/declare/local/readonly/export) that
look like assignment statements don't kick in. Hence the statement
above that the `(6 7 8)' doesn't get split only by chance.
What happens is that `declare' sees as its argument `a=(6 7 8)' due to
the combination of those two factors, and performs the array assignment.
I have changed the parser so stuff like this gets caught at parse time
rather than at evaluation. It will be more consistent. The parser
shouldn't try to be so helpful when the rest of the shell isn't going
to treat it as an assignment statement.
> bash-2.05$ declare -a $foo=($*)
> bash: declare: a: cannot assign to array variables in this way
> bash: declare: `4': not a valid identifier
> bash: declare: `5)': not a valid identifier
In this case, however, the $* gets split. Again, the `$foo=($*)' is
not an assignment statement, the heuristics don't kick in, and what
declare actually sees is
+ declare -a 'a=(3' 4 '5)'
(run set -x and you'll see what I'm talking about). If you were to use
something like
eval declare -a $foo='($*)'
you'd get the behavior you want.
> bash-2.05$ set 1 2 3
> bash-2.05$ declare -a a=($@)
This works as intended. The `a=($@)' is a valid assignment statement,
the word splitting is inhibited, and a is assigned 1 2 3.
> bash-2.05$ echo ${a[$*]}
> bash: 1 2 3: syntax error in expression (error token is "2 3")
I don't know what you expect this to do.
> bash-2.05$ declare -a $foo=($@)
> bash: declare: a: cannot assign to array variables in this way
> bash: declare: `2': not a valid identifier
> bash: declare: `3)': not a valid identifier
The same thing as above. Using
eval declare -a $foo='($@)'
works.
Chet
--
``The lyf so short, the craft so long to lerne.'' - Chaucer
( ``Discere est Dolere'' -- chet)
Chet Ramey, CWRU chet@po.CWRU.Edu http://cnswww.cns.cwru.edu/~chet/