Home > Mobile >  how do i loop through an array of numbers and update the array in bash using the array values
how do i loop through an array of numbers and update the array in bash using the array values

Time:11-26

I am trying to increase the values of an array of integers using a variable, but it doesn't seem to be accessing the array values properly. It is to start from 0 in an ascending order, while incrementing the current array value at each iteration. I tried this:

array=(2 0 1)
tag=(H H H)
count=0

for i in ${array[@]}
do
    if [[ "$array[$i]"="$count" ]]
    then
        array[$i]=$((${array[$i]} 1)) 
        tag[$i]="C"
    fi
count=$(($count   1))
done

Instead it kept updating from 2, then 1, before 0. I want it to start from 0, since that is the index that is equal to count. This was the output.

 0       H H C
         2 0 2

 1       C H C
         3 0 2

 2       C C C
         3 1 2

CodePudding user response:

One problem is that the values you are retrieving with the for loop are integers that are being used as indexes to update the values of the array. A second problem is that your conditional statement is actually an assignment, so its exit code is always 0 (true), so $count, though incrementing, affects nothing.

First time through, $i==2, the third element of array is incremented (array[2]==2), the third element of the tag array is set to changed

The second time through, $i==0, the first element of array is incremented (array[0]==3), the first element of tag array is set to changed.

The third time through, $i==1 (see comment below), the second element of array is incremented (array[1]==1), and the second element of the tag array is set to changed.

Promised comment: In the third iteration, other languages would have $i==2 because array[2] had been incremented in the first loop. Bash is apparently iterating over the original values of the array, despite subsequent changes.

I think what you want to do is:

declare -a array=(2 0 1)
declare -a tag=("here" "here" "here")
declare -i count=0
declare -i i

echo "$count:  ${array[*]}"
echo "   ${tag[*]}"

for (( i=0; i<${#array[*]};   i )); do
    (( array[i]   ))   # no need for '$' within (( ))
    tag[$i]="changed"
    (( count   ))
    echo "$count:  ${array[*]}"
    echo "   ${tag[*]}"
done

I didn't include your conditional because I can't figure out what you're trying to do with it.

I added the echo statements to create output similar to the output you claimed in your example.

CodePudding user response:

In the loop iteration you are using array values instead of array indices, which is the core of the problem. So the TL;DR is: "${!array[@]}".

array=(2 0 1)
tag=(H H H)
echo "${array[@]@A}; ${tag[@]@A};"

for index in "${!array[@]}"; do
  ((  array[index]))
  tag[index]=C
  echo "${array[@]@A}; ${tag[@]@A};"
done

Output:

declare -a array=([0]="2" [1]="0" [2]="1"); declare -a tag=([0]="H" [1]="H" [2]="H");
declare -a array=([0]="3" [1]="0" [2]="1"); declare -a tag=([0]="C" [1]="H" [2]="H");
declare -a array=([0]="3" [1]="1" [2]="1"); declare -a tag=([0]="C" [1]="C" [2]="H");
declare -a array=([0]="3" [1]="1" [2]="2"); declare -a tag=([0]="C" [1]="C" [2]="C");

CodePudding user response:

FYI: Bash indexing starts from 0 (so to change the 2-nd element you should consider index No. 1) script.sh

#!/bin/bash

array=(2 0 1)
tag=(H H H)

for i in `seq 1 ${#array[@]}` ;do
  (( i-- ))
  ii="${array[i]}"
  (( ii-- ))
  tag[$ii]="C"
  #(( array[i]   ))
  echo -e "$i:\t${tag[@]} \n\t${array[@]}"
done

Output of the script.sh:

0:  H C H 
    2 0 1
1:  H C C 
    2 0 1
2:  C C C 
    2 0 1

Update:

Just seen your comment, will try to update my script.

I want it to start from the array value 0, which is is the middle. So it should look like this, H C H > H C C > C C C

Script Updated, please check again!

  • Related