0

I have these variables:

bridge_xa_name_list=( "$br_int0_srxa" "$br_int1_srxa" "$br_int2_srxa" "$br_int6_srxa" "$br_int7_srxa" "$br_wan3_srxa1" "$br_wan3_srxa2" )
bridge_xb_name_list=( "$br_int0_srxb" "$br_int1_srxb" "$br_int2_srxb" "$br_int6_srxb" "$br_int7_srxb" "$br_wan3_srxb1" "$br_wan3_srxb2" )

I am trying to use a single loop to iterate all the elements for each array.

At the moment I have a functioning loop but only by referencing the $bridge_xa_name_list

   for a in "${bridge_xa_name_list[@]}"; do
        shell_echo_textval_green "Network Bridge Name Detected" "$a"

        sleep 1
        shell_echo_text "Verifying $a network State"
        virsh_net_list=$(virsh net-list | grep active | grep $a)    

        if [[ ! $virsh_net_list == *"active" ]]
        then
            shell_echo "[Inactive]"
        else
            shell_echo "[Active]"
            shell_echo_green "$a.xml found. Undefining anyway."
            virsh net-undefine $a
        fi
            
        shell_echo_text "File $a.xml is at $srxa_fld_path"
        if [[ -f ${srxa_fld_path}${a}.xml ]]
        then
            shell_echo "[Yes]"
        else
            shell_echo "[Not Found]"
            shell_echo_text "Attempting to copy $a.xml template to ~/config/$srxa_nm"
            cp $xml_file_path $srxa_fld_path${a}.xml
            shell_echo ["Copied"]

            #Check if Copy was sucessfull
                if [[ -f $srxa_fld_path${a}.xml ]]
                then    
                    :
                else
                    shell_echo_red "[Failed]"
                    shell_echo_red "There was an error when trying to copy ${a}.xml"
                    shell_echo_error_banner "Script Aborted! 1 error(s)"
                    exit 1              
                fi
done

$a in my script is iterating all the elements from the 1st array. However, I would like to include the second array as part of the same loop.

7
  • Your script starts with 2 equal lines for a in "${bridge_xa_name_list[@]}"; do. Remove one of them or change the second into for b in "${bridge_xb_name_list[@]}"; do. Commented May 1, 2022 at 12:54
  • Lol That was a typo. I copied the loop twice Sorry Commented May 1, 2022 at 13:00
  • When you say you want to use just one variable to access both arrays within the same loop, do you mean to access corresponding elements of the two arrays both in the same iteration? Or would it be sufficient to simply loop over all the xas followed by all the xbs? Commented May 1, 2022 at 13:14
  • 1
    Is that script really the briefest script you could come up with to demonstrate the problem you're asking for help with? I suspect it isn't - please create and post a minimal reproducible example that just demonstrates the problem, don't just post whatever code you have lying around that contains the problem somewhere within it. See How to Ask. Commented May 1, 2022 at 13:53
  • a minimal example should consist of the the loop(s) and some echo calls to display the loop variables; all of the shell_echo*, cp, virsh, if/then/else/fi code is just noise and doesn't appear to have anything to do with the main objective of iterating between arrays Commented May 1, 2022 at 14:33

2 Answers 2

4

These are indexed arrays so you can iterate over the indexes:

for (( i = 0; i < ${#bridge_xa_name_list[@]}; i++ )); do
  echo "${bridge_xa_name_list[i]}"
  echo "${bridge_xb_name_list[i]}"
done
Sign up to request clarification or add additional context in comments.

2 Comments

Doesn't that mean that I would need to expand my script double to fit the other array? Is there a way to reference both arrays within one letter like $a? Sorry I'm not an expert in bash. I'll update the question a portion of the script so you know what I mean
You can change the lines with echo like a="${bridge_xa_name_list[i]}" and b="${bridge_xb_name_list[i]}". This solution will only iterate over pairs (a,b) where they have the same index in the arrays. When you want all combinations of elements from both arrays, your question was unclear.
1

$a in my script is iterating all the elements from the 1st array. However, I would like to include the second array as part of the same loop.

I think you mean that you want to execute the loop body once for each element of bridge_xa_name_list and also once, separately, for each element of bridge_xb_name_list, without duplicating the body of the loop. Yes, there are at least two easy ways to do that:

  1. Absolutely easiest would be to just specify the additional elements in the loop header:

    for a in "${bridge_xa_name_list[@]}" "${bridge_xb_name_list[@]}"; do
      # loop body ...
    

    What you need to understand here is that the for loop syntax has nothing in particular to do with accessing an array. The in list of such a command designates zero or more individual values (shell "words") to iterate over, which in the case of your original code are produced by a parameter expansion involving array-valued parameter bridge_xa_name_list. But this is just a special case of the shell's general procedure of expanding each command (path expansion, parameter expansion, command expansion, etc.) before executing it. You can use that however you like.

    OR

  2. Make a function around the loop that executes it once for every function argument. Then call that function once for each array:

    my_loop() {
      for a in "$@"; do
        # loop body
      done
    }
    
    # ...
    
    my_loop "${bridge_xa_name_list[@]}"
    my_loop "${bridge_xb_name_list[@]}"
    

    Note that this still exhibits the same expand-then-execute behavior described in the previous item, which is why you have to pass the expansion of each array (to one word per element). There is no direct way to pass the whole array as a single argument.

    Note also that the shell supports a special shortcut for iterating over all the elements of $@. For that particular case, you can omit the in list altogether:

    my_loop() {
      for a; do
        # loop body
      done
    }
    

Of course, you can also combine the above, by providing the function and calling it once with the elements of both arrays:

my_loop "${bridge_xa_name_list[@]}" "${bridge_xb_name_list[@]}"

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.