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.