[Cialug] Bash looping issue

Crouse crouse at usalug.net
Wed Oct 13 15:12:40 CDT 2010


On Wed, Oct 13, 2010 at 1:14 PM, Crouse <crouse at usalug.net> wrote:
> ah nm... that went horribly wrong ;)
>
>
> On Wed, Oct 13, 2010 at 1:12 PM, Crouse <crouse at usalug.net> wrote:
>> On Wed, Oct 13, 2010 at 11:18 AM, Ken MacLeod <ken at bitsko.slc.ut.us> wrote:
>>> On Tue, Oct 12, 2010 at 10:07 AM, Daniel A. Ramaley
>>> <daniel.ramaley at drake.edu> wrote:
>>>> In the example script below, i define an associative array and then make
>>>> a copy of it using a loop to copy each key/value pair. It seems to work
>>>> quite nicely... within the loop. Once outside the loop, the copied array
>>>> loses its data. The bizarre thing is that if i switch the loop construct
>>>> from a "while" to a "for", it works.
>>>
>>>> # Comment out the "printf...while" loop and comment in the "for" loop
>>>> # and it magically starts working. I don't know why.
>>>> printf "%s\000" "${!ORIG[@]}" | sort -z | while read -d $'\0' key ; do
>>>> #for key in "${!ORIG[@]}" ; do
>>>
>>> My first thought is that the "while" is running in a pipeline so it's
>>> running in a subprocess rather than the current process, so any
>>> variables inside the loop are local to the subprocess.  However, I
>>> thought I've done that before too and it worked right...
>>>
>>> You might try:
>>>
>>>    while read -d $'\0' key <(printf "%s\000" "${!ORIG[@]}" | sort -z); do
>>>
>>> so the printf | sort runs in a background process and the while stays
>>> in the current process.  I've never tried that before but it popped up
>>> when I went looking for the other kinds of "fancy" pipe handling that
>>> I know bash has ;-)
>>>
>>>  -- Ken
>>> _______________________________________________
>>> Cialug mailing list
>>> Cialug at cialug.org
>>> http://cialug.org/mailman/listinfo/cialug
>>>
>>
>> If your just copying an array, do you need to use the while loop ?
>>
>> #!/bin/bash
>> declare -A ORIG
>> ORIG=(['key 1']='A'
>>     ['key 2']='B'
>>     ['key 3']='C')
>>
>> COPY=("${ORIG[@]}")
>>
>> echo -e "\nORIG\n----"
>> for key in "${!ORIG[@]}" ; do     # Prints the ORIG array.
>>   echo -e "$key\t${ORIG[$key]}"
>> done
>>
>> echo -e "\nCOPY\n----"
>> for key in "${!COPY[@]}" ; do     # Prints COPY only if it was created
>>   echo -e "$key\t${COPY[$key]}" # with "for" loop--prints nothing if
>> done                              # created with "while".
>>
>


Well after some looking, I found this:
http://mywiki.wooledge.org/BashGuide/Arrays
"the order of the keys you get back from an associative array using
the ${!array[@]} syntax is unpredictable; it won't necessarily be the
order in which you assigned elements, or any kind of sorted order. "

Handy..... not sure this really helps at all, but I did find it interesting.

#!/bin/bash
declare -A ORIG
ORIG=(['key 1']='A'
     ['key 2']='B'
     ['key 3']='C')

declare -A COPY

# Create list of keys
for key in "${!ORIG[@]}" ; do
echo "$key" >> temp
done
# Sort list of keys
cat temp | sort > temp2

while read mykey ; do
   COPY["${mykey}"]="${ORIG[$mykey]}"
   #COPY+=(["${key}"]="${ORIG[$key]}") # Alternate form of assignment
   echo -e "DEBUG:\tProcessing key=\"${mykey}\", val=\"${ORIG[$mykey]}\""
  # echo -e "DEBUG:\t${!COPY[@]}\nDEBUG:\t${COPY[@]}" ; # Shows changes
done < temp2

# remove temp files
rm temp temp2

#for key in "${!ORIG[@]}" ; do
#   COPY["${key}"]="${ORIG[$key]}"
   #COPY+=(["${key}"]="${ORIG[$key]}") # Alternate form of assignment
#   echo -e "DEBUG:\tProcessing key=\"${key}\", val=\"${ORIG[$key]}\""
#   echo -e "DEBUG:\t${!COPY[@]}\nDEBUG:\t${COPY[@]}" ; # Shows changes
#done<( printf "%s\000" "${!ORIG[@]}" | sort -z )


echo -e "\nORIG\n----"
for key in "${!ORIG[@]}" ; do     # Prints the ORIG array.
   echo -e "$key\t${ORIG[$key]}"
done

echo -e "\nCOPY\n----"
for key in "${!COPY[@]}" ; do     # Prints COPY only if it was created
   echo -e "$key\t${COPY[$key]}" # with "for" loop--prints nothing if
done                              # created with "while".

~
~
~
~
~
~
~
~
~
~
~
~
~
[crouse at Archie]  ~
> ./cialug
DEBUG:  Processing key="key 1", val="A"
DEBUG:  Processing key="key 2", val="B"
DEBUG:  Processing key="key 3", val="C"

ORIG
----
key 1   A
key 3   C
key 2   B

COPY
----
key 1   A
key 3   C
key 2   B


More information about the Cialug mailing list