I'm trying to loop through an array that contains other arrays and these arrays consist of strings with spaces. The problem is that I can't seem to preserve the spacing in the string. The string with spaces are either divided into multiple items if I change IFS to \n or all the elements of the array are seen as 1 item if I leave IFS unchanged here's some sample code:
#!/bin/sh
low1=("AA  QQ" "BB  LL")
low2=("CC" "DD")
low3=("EE" "FF")
high=(low1 low2 low3)
for high_item in ${high[@]}
do
   eval arrayz=\${$high_item[@]}
   #IFS=$'\n'
   for item in $arrayz
   do
      echo $item
   done
done
Output:
AA QQ BB LL CC DD EE FF
As you can see the elements "AA QQ" and "BB LL" have been split.
If I uncomment the line that sets IFS to \n I get the following:
AA QQ BB LL CC DD EE FF
Now "AA QQ" and "BB LL" are concatenated!
Is there anyway I can preserve these elements just as they original are...I need the output to look like that:
AA QQ BB LL CC DD EE FF
I think you meant that the output should look like:
AA  QQ
BB  LL
CC
DD
EE
FF
i.e.:
${low1[0]}
${low1[1]}
${low2[0]}
${low2[1]}
${low3[0]}
${low3[1]}
This could be accomplished using:
#!/bin/bash
low1=("AA  QQ" "BB  LL")
low2=("CC" "DD")
low3=("EE" "FF")
high=(low1 low2 low3)
for high_item in ${high[@]}
do
    x="${high_item}[@]" # -> "low1[@]"
    arrays=( "${!x}" )
    #IFS=$'\n'
    for item in "${arrays[@]}"
    do
        echo "$item"
    done
done
And please always use #!/bin/bash for bash scripts.
Explanation: ${!x} is indirect variable expansion. It evaluates to the value of variable with a name contained in $x.
For our needs, x needs to have the [@] suffix for array expansion as well. Especially note that it is x=${high_item}[@] and not x=${high_item[@]}.
And you have to evaluate it in array context; otherwise, it wouldn't work as expected (if you do arrays=${!x}).
Ah, and as final note: IFS doesn't make any difference here. As long as you are working on quoted arrays, IFS doesn't come into play.
Replace eval with indirect parameter expansion, and you'll get what I think you want (although it doesn't match your current given output:
for high_item in "${high[@]}"
do
    arrayz="$high_item[@]"
    # arrayz is just a string like "low1[@]"
    for item in "${!arrayz}"
    do
        echo $item
    done
done
Note the need to quote the array expansion in the inner loop to preserve the whitespace in elements of low1.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With