[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Problem with how to assign an array
From: |
Ken Irving |
Subject: |
Re: Problem with how to assign an array |
Date: |
Thu, 24 Feb 2011 13:00:33 -0900 |
User-agent: |
Mutt/1.5.20 (2009-06-14) |
On Thu, Feb 24, 2011 at 03:42:57PM -0500, Greg Wooledge wrote:
> On Thu, Feb 24, 2011 at 02:55:13PM -0500, Steven W. Orr wrote:
> > I have three arrays
> >
> > a1=(aaa bbb ccc ddd)
> > a2=(qqq www eee rrr)
> > a3=(fff ggg hhh)
> >
> > I then set a_all
> >
> > a_all=("${a1[*]}" "${a2[*]}" "${a3[*]}"
>
> Missing ). Also, a far more serious problem, you used * when you should
> have used @.
>
> a_all=("${a1[@]}" "${a2[@]}" "${a3[@]}")
>
> This is absolutely critical. Without this, you are no longer maintaining
> the integrity of each element. In fact, what you've got there will create
> a_all with precisely 3 elements. Each of these elements will be a
> concatenation of the other arrays' elements with a space (or the first
> char of IFS if you've set that) between them.
>
> > Later on, I decide which element of a_all I really want. So with my new
> > index calculated, I say
> >
> > real_a=( ${a_all[index]} )
>
> This is also wrong. This one does word-splitting on the element you're
> indexing, and the resulting set of words becomes a new array.
But if * was used in declaring the a_al elements, this _would_ recover
one of the arrays, e.g., real_a=(${a_all[1]}) should result in the same
array as a2. (Ignoring the null-element issue, though.)
I had the same thought, use @ instead of *, but maybe the OP wants to
get the original arrays and not individual elements?
> In fact, I can only guess what you're trying to do here.
>
> If you want to assign a single element to a scalar variable, you
> should do: element=${array[index]}
>
> > And it worked really well until today. The problem is that I need an
> > element of the aNs to be allowed to be null values.
As explained, using * expands '' or ' ' into just word-delimiting whitespace,
so the null elements are lost.
> No problem.
>
> > Like this:
> >
> > a1=(aaa bbb ccc ddd '' jjj kkk lll)
>
> No problem.
>
> > such that if index is 0, I'd like real_a to end up with 8 elements instead
> > of 7.
>
> Huh? You mean during the concatenation? (You changed the array name?)
> Do it correctly:
>
> imadev:~$ unset a1 a2 big; a1=(a b '' c) a2=(d e f '')
> imadev:~$ big=("${a1[@]}" "${a2[@]}")
> imadev:~$ printf "<%s> " "${big[@]}"; echo
> <a> <b> <> <c> <d> <e> <f> <>
>
> > I could create a sentinel, I could use a case statement, I could create all
> > kinds of confabulations, but I'd like to know if there's a better way to do
> > it.
>
> Huh?
If by sentinel you (OP) mean a token standing in for null, I suspect that would
be the simplest approach.
> > I literally tried everything I could think of.
Listen to Greg...
Ken
> You must learn the difference between "$*" and "$@". (And the analogous
> treatment of * and @ in an array indexing context.)
>
> imadev:~$ wrong=("${a1[*]}" "${a2[*]}")
> imadev:~$ printf "<%s> " "${wrong[@]}"; echo
> <a b c> <d e f >
>
> If you don't use the right syntax, you're going to have problems with
> elements that contain whitespace (or IFS characters) as well as empty
> elements as you already noted.