Assign ksh array value incorrectly

Have a ksh script below:

cat s.ksh
 #!/bin/ksh
 _COMB=";B;;D;"
 set -A arr $( echo ${_COMB} | awk -F";" '{print $1, $2, $3, $4. $5}' )

for i in (0..5)
do
   if [[ "x${arr[$i]}" = "x" ]]; then
     ${arr[$i]}=' '
   fi
   echo "=${arr[$i]}="
done

When running it, expect to get the following:
= =
=B=
= =
=D=
= =
But I got the different results. Can any gurus shed some light on it? Can it be simplified? I need the array with data for late use.
jl66ConsultantAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

arnoldCommented:
Have not had chance to test, though assignment
Correct assignment
Var='data'
echo $Var

$Var='data'
echo $Var
You will get the result you have.

Note your array assignment into arr

I think your array access is not correct $arr[0] your ${arr[0]} I think is not correct.
Mark BullockQA EngineerCommented:
The problem is with this statement:
_COMB=";B;;D;"

Open in new window

There is an empty string before the B, between B and D, and after D.
So awk gets only two fields, B and D.
and arr[0]=B, arr[1]=D, and arr[2] through arr[4] are empty.
Surranoapplication managerCommented:
Mark, awk does get five fields but the awk command emits " B D " which is interpreted by "set" as two elements:
set -A  B D 

Open in new window

Instead of:
set -A "" "B" "" "D" "" 

Open in new window

Which would actually yield the expected result.

jl66, please try this. I'm not sure since I have mksh at hand but it worked.
eval $(echo ${_COMB} | awk -F";" '{for(i=1;i<=NF;i++) print "arr["(i-1)"]=\""$i"\""}')
for i in `seq 0 4`; do
if [[ "x${arr[$i]}" = "x" ]]; then
arr[$i]=' '
 fi
   echo "=${arr[$i]}="
done

Open in new window


Note that first I generated the assignment commands one by one instead of using "set -A". Not the most beautiful solution but if I tried to produce a correct input as above then set received the double quotes as part of the string literals and not as separate strings.

Also in the "set default" line I'm not sure if ksh proper would accept your form, just as arnold wrote... mksh didn't like it so I used the traditional form instead.
Determine the Perfect Price for Your IT Services

Do you wonder if your IT business is truly profitable or if you should raise your prices? Learn how to calculate your overhead burden with our free interactive tool and use it to determine the right price for your IT services. Download your free eBook now!

Gerwin Jansen, EE MVETopic Advisor Commented:
Your awk statement has an error:
{print $1, $2, $3, $4. $5}'

should be:
{print $1, $2, $3, $4, $5}'

But there's more wrong, the for loop for example. I've corrected your script:

#!/bin/ksh
_COMB=";B;;D;"
set -A arr $(echo ${_COMB} | awk -F";" '{print $1, $2, $3, $4, $5}')

for i in {0..4}
do 
   if [[ "x${arr[$i]}" = "x" ]]; then
     arr[$i]=' '
   fi
   echo "=${arr[$i]}="
done

Open in new window


What you expect to get will not work because your COMB array is containing empty values. So the awk line will print:

B D

So your output will be:

=B=
=D=
= =
= =
= =

Note that your for loop is 0..4 (not 5) to get 5 iterations (0,1,2,3,4)
arnoldCommented:
After some checking the ksh array is dereferenced as posted by the asker, assignment of an array value must nor be dereferenced. arr[0]='new value' will be output when echo ${arr[0]}

The issue with set -A is that it needs a list of items, and empty/white spaces are ignored. awk out puts the list with white space seperators to do what you want, your awk statement needs to be properly encoded to include the enclosing double quotes around every entry.
awk -F";" '{print "\""$1"\"","\""$2"\"","\""$3"\"","\""$4"\"","\""$5"\"", } '
this will output
"" "B" "" "D" ""

You could pass the script as you have to another pass
|perl -pe 's/(.)/\"$1\"/gi;'
but your output will include ......... " "...

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
jl66ConsultantAuthor Commented:
Thanks a lot for everyone's tips/solutions. Various solutions from the gifted gurus.

Can the following array assignment include the "if" statement to add one space if a specific elment of the array is null?
eval $(echo ${_COMB} | awk -F";" '{for(i=1;i<=NF;i++) print "arr["(i-1)"]=\""$i"\""}')
arnoldCommented:
I do not believe your awk programming is correct.
Besides the ' and () mismatches

Replace your awk example with the obe I posted, then adjust the spacing by removing the ${} around arr[$i] in the loop assignment.

From the combinations you should get what you are looking for, though this is static.

My awk programming beyond single line,,,, often this is part of a more complex where perl might be an alternative, though it likely gas higher overhead as an interpreted

Begin
Look through elements of awk, check if length of an element is an empty set, and then output.......
jl66ConsultantAuthor Commented:
Thanks a lot. Appeciate everyone's contribution. Finally got exactly what was wanted within one line.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Shell Scripting

From novice to tech pro — start learning today.