ksh insert element in array

Hi all,

I need help with the following scenario in ksh.

If the number of elements contained by arrayA is 11 I need to insert a zero as the element arrayA[5] then print all arrayA elements separated by comma.

Appreciate your help.

Which ksh implementation and what did you try so far?

Version M-11/16/88i

Reading my post above I think I wasn't very specific. I do not want the 6th element to be replaced with zero. What I need is to insert a zero as the 6th element and shift everything that follows to the right.

What I tried was to split it into two arrays, but I have problems when I assign array values.

Can you show the code you were trying please? Use

```text
 and 
```

tags, when doing so, thanks.

I believe that with ksh88 you'll need to loop and set/adjust the elements manually. As zaxxon said: post your code and we will try to suggest a fix.

You may have to count your way along the array with two pointers. A source address and a target address for a replacement array. The source address gets incremented each time through a loop to copy an element from one to the other, but within the loop there would be an extra increment to the target address and an insert of the zero in the position you want. Something like this may assist:-

#!/bin/ksh
set -a source_array
set -a target_array

for i in 1 2 3 4 5 6 7 8 9 10 11 12
do                                  # Just loading something into the source.
   source_array[$i]="a${i}a${i}"    # You should already have your data loaded.
done

src_addr=1 ; trg_addr=1

while [ $src_addr -le ${#source_array[*]} ]
do
   target_array[$trg_addr]="${source_array[$src_addr]}"
   echo "Setting target array element $trg_addr from source array element $src_addr value ${source_array[$src_addr]}"
   ((src_addr=$src_addr+1))
   ((trg_addr=$trg_addr+1))

   if [ $trg_addr = 6 ]              # For the required insert
   then
      target_array[$trg_addr]=0    # Set value
      echo "Setting target array element $trg_addr as zero."
      ((trg_addr=$trg_addr+1))   # ... and move pointer along one
   fi
done

I hope that this helps. It may well not be the most efficient way, but it depends how big an array you have and how many times you will run this.

Robin
Liverpool/Blackburn
UK

My thought was to shift the elements of the array over by one until we hit the one that needs to be zero. I assumed the sixth element based on the index as arrays are zero-based. You may have to adjust accordingly:

$ cat x
#!/bin/ksh

## Create the starting array with 11 elements.  Arrays are
## zero-based, so they would be elements 0-10.
set -A arrayA 1 2 3 4 5 6 7 8 9 10 11

## arrayA_pointer starts out equal to the number of elements in the array
## (11), thus points 1 past the end (arrayA[11] does not exist yet).
integer arrayA_pointer=$((${#arrayA[@]}))

integer ctr=0
typeset -ir INSERT_POINT=6

## Show the starting array.
print "Before: [${arrayA[@]}]"

## Loop backwards through the elements, shifting them to the value
## of the one before it, until we come to the element that needs
## to be set to 0.
while (( $arrayA_pointer > $INSERT_POINT )); do
  arrayA[${arrayA_pointer}]=${arrayA[${arrayA_pointer}-1]}
  (( arrayA_pointer=arrayA_pointer-1 ))
done

## We hit the element that needs to be set to 0.
arrayA[$arrayA_pointer]=0

## Loop through the processed array, printing out each element.
printf "After: "
while (( ${ctr} < ${#arrayA[@]} )); do
  if (( ${ctr} + 1  == ${#arrayA[@]} )); then
    printf "%s\n" ${arrayA[$ctr]}
  else
    printf "%s, " ${arrayA[$ctr]}
  fi
  (( ctr=ctr+1 ))
done

exit 0
$ x
Before: [1 2 3 4 5 6 7 8 9 10 11]
After: 1, 2, 3, 4, 5, 6, 0, 7, 8, 9, 10, 11
$

All,

Thank you all for your prompt responses. Tomorrow I will be able to test what you've suggested and get back to you with what worked.

A different approach that I had prepared in case you show your doing 1st - nevertheless - maybe helpful too. Single steps; the test for 11 shouldn't be the problem:

# cat blafile
# set -A arrayA a b c d e f g h i j g
# echo ${arrayA[*]}
a b c d e f g h i j g
# echo ${#arrayA[*]}
11
# TMP=$(echo ${arrayA[*]}| awk '{$5=0 FS $5; print}')
# set -A arrayA $(echo $TMP)
# echo ${arrayA[*]}| tr -s " " ","
a,b,c,d,0,e,f,g,h,i,j,g
1 Like

All,

I decided to go with zaxxon's approach. Below is how the code looks now. It almost does what I want which is to get the numbers out of top and create statistics that give better view over time. But for some reason the line below excludes the CPU states from the output of top. I'll be looking into that and also a better way to report top ten cpu, time, size, res to make it easier to read instead of numbers. Thank you all for your help.

$tp -n 0 > $gnTmp

Below is how $gnTmp looks like, CPU stats line missing.

load averages:  4.03,  3.95,  3.79    03:49:09
1179 processes:1041 sleeping, 134 zombie, 4 on cpu

Memory: 32G real, 16G free, 19G swap in use, 14G swap free
wa=/some_path/top
log=/some_path/top/log.txt
tp=/path_to_top/top

MONTH=`date '+%B'`
DAY=`date '+%d'`
YEAR=`date '+%Y'`
TIME=`date '+%X'`
cpTmp=$wa/cpu.tmp
tmTmp=$wa/time.tmp
szTmp=$wa/size.tmp
rsTmp=$wa/res.tmp
gnTmp=$wa/gen.tmp
ovOut=$wa/overview.out
cpu=$wa/topCPU.out
tme=$wa/topTime.out
siz=$wa/topSize.out
res=$wa/topRes.out

### Gathering top output
$tp -n 0 > $gnTmp
$tp -o cpu -n 10 > $cpTmp
$tp -o time -n 10 > $tmTmp
$tp -o size -n 10 > $szTmp
$tp -o res -n 10 > $rsTmp

### Processing and building output
ov=`sed 's/[A-Za-z ]*//g;s/[0-9]\{2\}:[0-9]\{2\}:[0-9]\{2\}//g;s/^://;s/:/,/;/^$/d' $gnTmp | sed -e ':a' -e '$!N;s/\n/,/;ta'`
ut=`uptime | awk '{print $3}'`
bt=`who -b | awk '{print $4$5,$6}'`

### Create an array out of ov
typeset IFS=,
set -A Ovarray $( print "${ov}" )
set | grep Ovarray

### Test the length of array
Array_length=${#Ovarray
[*]}
#echo "Array length is $Array_length"

if [ $Array_length -eq 11 ];
        then
        #       print "Then Array length is 11"
        #       print ${Ovarray
[*]}
        #       print ${#Ovarray
[*]}
                TMP=$(print ${Ovarray
[*]}| awk '{$5=0 FS $5; print}')
                set -A Ovarray $(echo $TMP)
#               print ${Ovarray
[*]}| tr -s " " ","
                ov=`print ${Ovarray
[*]}| tr -s " " ","`
        else
                print "Else " >> $log
                print $Array_length >> $log
fi

echo "$ut,$ov,$bt,$YEAR,$MONTH,$DAY,$TIME" >> $ovOut

for row in `awk 'NR > 7 {print $1, $10}' $cpTmp`
do
echo "$row,\c" >> $cpu
done
printf "$YEAR,$MONTH,$DAY,$TIME\n" >> $cpu

for row in `awk 'NR > 7 {print $1, $9}' $tmTmp`
do
echo "$row,\c" >> $tme
done
printf "$YEAR,$MONTH,$DAY,$TIME\n" >> $tme

for row in `awk 'NR > 7 {print $1, $6}' $szTmp`
do
echo "$row,\c" >> $siz
done
printf "$YEAR,$MONTH,$DAY,$TIME\n" >> $siz

for row in `awk 'NR > 7 {print $1, $7}' $rsTmp`
do
echo "$row,\c" >> $res
done
printf "$YEAR,$MONTH,$DAY,$TIME\n" >> $res