2

In a for loop I am looking to find out: If Array1 length matches Array2 length then break the for loop.

Shellcheck throws an error (while the script runs fine)

    if [[ "${!Array1[@]}" == "${!Array2[@]}" ]] ; then
            break;
    fi

^-- SC2199: Arrays implicitly concatenate in [[ ]]. Use a loop (or explicit * instead of @).

I'm still learning bash and my teacher said "Always verify with Shellcheck" and to "always place conditionals in double [[ ]]" and to "never use * for array length"

The error(s) are removed with the correction

    if [ "${!Array1[*]}" == "${!Array2[*]}" ] ; then
            break;
    fi

I was wondering what is the best practice here?

2
  • If by length you mean the number of elements, "${!Array1[@]}" is wrong. Commented Sep 25, 2017 at 7:35
  • Obtain the length of (count of elements in) an array with "${#array[@]}". Commented Sep 25, 2017 at 7:37

2 Answers 2

1

Your code is partly correct. The problem is, that you are expanding the array's indicies with th ! operator, and not the length by using the # operator.

Thus a warning about implicit concatenation is issued for both uses of ${array[@]}, as the list of indicies is 0 1 2 3 .... Nevertheless your code is working, as two non associative bash arrays with equal length will have identical index lists 0 1 2 .. N.

To get rid of the warning, you should replace ${!array[@]} with ${#array[@]}. Of course, using ${!array[*]} will also suppress the warning, but that is definitely not what you want to do here, as you would continue comparing index lists.

For further reading: The author of shellcheck has explained the concatenation issue here in detail.

Sign up to request clarification or add additional context in comments.

1 Comment

two non associative bash arrays with equal length will have identical index lists 0 1 2 .. N This is generally not true, as there may be gaps in the used values of indices, e.g. declare -a a='([0]="a" [1]="b" [10]="c")' for which ${#a[@]} evaluates to 3 and ${#a[@]} is 0 1 10.
0

Nyronium's works well and explains the solution perfectly.

I also found a solution that utilities # to check the array length for the condition.

Sorry I did not have this example script before, as I wrote it to test logic afterwards.

Example

#!/bin/bash
array1=(1 2 3)
array2=()

echo "array1 length: ${#array1[@]}" #output :3

for i in {1..10} ; do
        echo "array2 length: ${#array2[@]}"
        array2+=("$i")

        #I want to exit when array2 = a length of 3
        if [[ "${#array1[@]}" == "${#array2[@]}" ]] ; then
                echo "exit"
                break
        fi
done

echo "final array1 length: ${#array1[@]} vs array2 length: ${#array1[@]}"

Result: final array1 length: 3 vs array2 length: 3

Comments

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.