1

I'm trying to execute a for loop in bash script where I have the requirement to pass two variables. I'm currently using the below for loop without success.

IFS=',' ;for componentId in `echo "${componentIds}"`, packageVersion in `echo "${packageVersions}"`; 
do 
    notes="${saveNotes}"
    deployNotes="${saveNotes}"
packageVersion=`echo "${packageVersion}" | xargs`
savePackageVersion="${packageVersion}"
componentId=`echo "${componentId}" | xargs`
saveComponentId="${componentId}"
    componentType="${saveComponentType}"
    listenerStatus="${saveListenerStatus}"
    envId=${saveEnvId}
    source bin/createSinglePackage.sh componentId=${componentId} componentType="${componentType}" packageVersion="${packageVersion}" notes="${notes}" extractComponentXmlFolder="${extractComponentXmlFolder}" componentVersion=""
done   

So I want to iterate the above for loop with both componentId and packageVersion variables using command substitution where the values of ${componentIds} and ${packageVersions} are already set as env variables. So I'm just trying to echo that and get the output. The output values of these variables are delimited by , and hence the IFS=','

When i execute my current script it complains about missing parameter packageVersion.

Any suggestions to address this would be quite helpful, thank you!!

Vamsi
  • 13
  • 3
  • 6
    Please add a suitable shebang (`#!/bin/bash`) and then paste your script at http://www.shellcheck.net/ and try to implement the recommendations made there. – Cyrus Jan 29 '23 at 09:02
  • Are you trying to iterate over both lists in parallel (i.e. first element of `$componentIds` with first element of `$packageVersions`, then second element of `$componentIds` with second element of `$packageVersions`, etc)? If so, converting them to proper arrays and using one of the methods in ["Iterate over two arrays simultaneously in bash"](https://stackoverflow.com/questions/17403498/iterate-over-two-arrays-simultaneously-in-bash) should work. Also, I second the recommendation of [shellcheck.net](https://www.shellcheck.net). – Gordon Davisson Jan 29 '23 at 09:04
  • @Cyrus Thanks, I have checked that but unable to figure out from there since my script calls multiple underlying scripts which shellcheck doesn't follow. – Vamsi Jan 29 '23 at 09:26
  • @GordonDavisson Yes, that's right because we are passing these two values as parameters to the script sourced in do statement. Specifically as below (Ignored few other parameters being passed as shown in my question just for easy reference) source bin/createSinglePackage.sh componentId=${componentId} packageVersion="${packageVersion}" – Vamsi Jan 29 '23 at 09:27
  • 1
    @Vamsi `I have checked that but unable to figure out from there since my script calls multiple underlying scripts which shellcheck doesn't follow`, but you do expect here that StackOverflow volunteer helpers will be able to figure-out what's wrong with your other unseen scripts. Use ShellCheck on all your scripts and fix everything it warns about. SC provides links to its Wiki, if you need help fixing specific warnings. – Léa Gris Jan 29 '23 at 11:08
  • Can you make a small loop without calling other scripts, show which which values of `${componentIds}` and `${packageVersions}` you start, the result you get and what you was hoping for? – Walter A Jan 29 '23 at 12:21

2 Answers2

0

You have two approaches you can take:

  • loop on each of the two parameters (if those are managed separately), or
  • loop on a matched set of parameters defined in an array.

Those two approaches are presented as logic_01 and logic_02 below:

logic_1()
{
IFS=',' 
for componentId in `echo "${componentIds}" `
do
    for packageVersion in `echo "${packageVersions}" `
    do
        notes="${saveNotes}"
        deployNotes="${saveNotes}"
        packageVersion=`echo "${packageVersion}" | xargs`
        savePackageVersion="${packageVersion}"
        componentId=`echo "${componentId}" | xargs`
        saveComponentId="${componentId}"
        componentType="${saveComponentType}"
        listenerStatus="${saveListenerStatus}"
        envId=${saveEnvId}

        source bin/createSinglePackage.sh \
            componentId=${componentId} \
            componentType="${componentType}" \
            packageVersion="${packageVersion}" \
            notes="${notes}" \
            extractComponentXmlFolder="${extractComponentXmlFolder}" \
            componentVersion=""
    done
done
}

... OR ...

logic_2()
{
packages=( "comp01:vers01" "comp01:vers02" "comp02:vers05" "comp02:vers06" "comp03:vers02" "comp03:vers04" )

for packages in ${packages[@]}
do
    componentId=`echo "${packages}" | cut -f1 -d\: `
    packageVersion=`echo "${packages}" | cut -f2 -d\: `

    notes="${saveNotes}"
    deployNotes="${saveNotes}"
    packageVersion=`echo "${packageVersion}" | xargs`
    savePackageVersion="${packageVersion}"
    componentId=`echo "${componentId}" | xargs`
    saveComponentId="${componentId}"
    componentType="${saveComponentType}"
    listenerStatus="${saveListenerStatus}"
    envId=${saveEnvId}

    source bin/createSinglePackage.sh \
        componentId=${componentId} \
        componentType="${componentType}" \
        packageVersion="${packageVersion}" \
        notes="${notes}" \
        extractComponentXmlFolder="${extractComponentXmlFolder}" \
        componentVersion=""
done
}
Eric Marceau
  • 1,601
  • 1
  • 8
  • 11
0

This Shellcheck-clean code illustrates one way to loop through two comma-separated lists at the same time:

#! /bin/bash -p

componentIds=compid1,compid2,compid3,compid4,compid5
packageVersions=pkgver1,pkgver2,pkgver3,pkgver4,pkgver5

IFS=, read -r -a compids <<<"$componentIds"
IFS=, read -r -a pkgvers <<<"$packageVersions"

for i in "${!compids[@]}"; do
    componentId=${compids[i]}
    packageVersion=${pkgvers[i]}
    printf 'componentId=%q, packageVersion=%q\n' "$componentId" "$packageVersion"
done
pjh
  • 6,388
  • 2
  • 16
  • 17