0

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
9
  • 1
    What should the array contain after the loop finishes? Commented Nov 25, 2022 at 17:20
  • 2
    start by cutting-n-pasting your code (along with appropriate shebang) into shellcheck.net and make the recommended changes; also consider that "${array[@]}" will give you a list of the array values while "${!array[@]}" will give you a list of the array indices Commented Nov 25, 2022 at 17:21
  • when it finishes array=(2 1 3) tags=(changed changed changed) Commented Nov 25, 2022 at 17:35
  • 2
    update the question to show the expected results; not everyone will read through comments trying to piece together the whole picture Commented Nov 25, 2022 at 17:36
  • 2
    I don't understand the question. You're already "looping through an array of numbers and updating the array", it's just not doing what you want. What are you trying to accomplish anyway? I saw your comment with your desired output, but what does that do for you? Beware the XY problem. Lastly, I don't understand the algorithm you're describing either. Could you break it down step by step? For more tips, like how to write a good title, see How to Ask. Commented Nov 25, 2022 at 18:13

4 Answers 4

3

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");
Sign up to request clarification or add additional context in comments.

Comments

0

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.

Comments

0

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

Note: Here the 0 in array is somehow equal to 3 - last element! (so, using 3 would be more user-friendly).

Assuming the $array values define the numbering element in $tag to be changed (ex. 2 for 2nd, 3 for 3rd, and so on) accordingly, the following script will do the job.

script.sh

#!/bin/bash
#array=(2 0 1) 

# Advantage of the logic of this script is that you may have more elements
# in $tag array but are able to change only a few of them that is mentioned in $array.
array=(2 3 1) # Change 2nd, 3rd, 1st elements accordingly.
tag=(H H H)

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

Output of the script.sh:

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

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!

4 Comments

ideally, I am trying to get the array from a file before putting in an array. How does declaring fit into that
@Ifeoma Provide your file example.
( A 1 2 B 2 0 C 2 1 ) the letters being the name of each. I will divide into separate arrays to hold the same array name [1] being the arrival time and [2] being the process time. I'm trying to print to the screen by accessing the array values itself and not the index number.
@Ifeoma , not sure If I got you successfully. Maybe I can take a look again next week. Until then please accept my answer if it satisfies your question. I'd also suggest updating your question (or better asking a new one) to contain a clear file example of the file and the requirement you look for.
0

I guess that you need two nesting loops in this case.

  • The outer loop is to scan the array once using count.
  • The inner loop is to identify the element that have value equal to count (0, then 1, then 2).
  • The tag array is to avoid increasing the same element twice.

OK, putting all that in code:

#!/bin/bash
array=(2 0 1)
tag=(H H H)
n=${#array[*]}                             ## array size
echo "${array[@]@A}; ${tag[@]@A};"         ## for testing
for (( count=0; count<n; ++count )); do
  for (( i=0; i<n; ++i )); do
    if [[ ${array[$i]} -eq $count && ${tag[$i]} = "H" ]]; then
      (( array[i]++ ))
      tag[$i]="C"                          ## C=changed
      break                                ## break inner loop
    fi
  done
  echo "${array[@]@A}; ${tag[@]@A};"       ## for testing
done

Results:

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

(sorry for my broken English)

1 Comment

I had to change the if statement to if [[ $array[$i]}=$count && $tag[$i]="H" ]]; then because I got "invalid assignment operator". But that only increments the item in the [0] element in array and tag

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.