Pass variable to a string in a shell file

8,808

Solution 1

You need to use doubles-quotes instead of single-quotes - single-quotes prevent variable expansion from taking place. Try this instead:

#!/bin/bash

NETWORKNAME=PCEXCHANGE
VERSION=1.1.0

ORGANIZATIONS=( "Asus" "Dell" "HP" "Amazon" )
PRODUCERS=( "Asus" "Dell" "HP" )
MAKERS=( "Amazon" )

for org in ${PRODUCERS[@]}
do
    for maker in ${MAKERS[@]}
        do
            docker exec cli.${maker} bash -c "peer channel create -c ${org,,} -f ./channels/${org}.tx -o orderer.${NETWORKNAME,,}.com:7050"
    done
done

Solution 2

To safely pass variables into a bash -c child shell, you would use

bash -c 'script goes here' bash "arg1" "arg2" "arg3" ...

That is,

#!/bin/bash

NETWORKNAME=PCEXCHANGE
VERSION=1.1.0

ORGANIZATIONS=( "Asus" "Dell" "HP" "Amazon" )
PRODUCERS=( "Asus" "Dell" "HP" )
MAKERS=( "Amazon" )

for org in "${PRODUCERS[@]}"; do
    for maker in "${MAKERS[@]}"; do
        docker exec "cli.$maker" \
            bash -c 'peer channel create -c "$1" -f "$2" -o "$3"' bash \
                "${org,,}" "./channels/$org.tx" "orderer.${NETWORKNAME,,}.com:7050"
    done
done

This would allow the child shell script to work even if any of the producers had spaces in their values.

Also note the quoting of the other expansions in the script, which makes it work even when producers or makers have spaces in their values.

The bash argument after the text of the bash -c script itself is what's passed into $0. This is usually the name of the script or the interpreter, so we simply pass the string bash.

Share:
8,808

Related videos on Youtube

0xSEGFAULT
Author by

0xSEGFAULT

I'm a software engineer for a startup.

Updated on September 18, 2022

Comments

  • 0xSEGFAULT
    0xSEGFAULT over 1 year

    I for some reason can't figure this out. I need the following to look like this. I basically don't want to write the same command 20-50 times depending or even more. Thanks!

    The problem with the current loop below is that the vars ${NETWORKNAME,,} inside the string in the command return an empty string. Example

    docker exec cli.Amazon bash -c 'peer channel create -c asus -f ./channels/Asus.tx -o orderer..com:7050'
    

    Which is obviously not a correct command

    What I'm looking for

    docker exec cli.Amazon bash -c 'peer channel create -c asus -f ./channels/Asus.tx -o orderer.pcexchange.com:7050'
    

    Current code

    #!/bin/bash
    
    NETWORKNAME=PCEXCHANGE
    VERSION=1.1.0
    
    ORGANIZATIONS=( "Asus" "Dell" "HP" "Amazon" )
    PRODUCERS=( "Asus" "Dell" "HP" )
    MAKERS=( "Amazon" )
    
    for org in ${PRODUCERS[@]}
    do
        for maker in ${MAKERS[@]}
            do
                docker exec cli.${maker} bash -c 'peer channel create -c ${org,,} -f ./channels/${org}.tx -o orderer.${NETWORKNAME,,}.com:7050'
        done
    done
    
    • 0xSEGFAULT
      0xSEGFAULT almost 6 years
      @ilkkachu hey man thanks for replying. I posted what I'm looking for in the edit above. Thanks!
  • igal
    igal almost 6 years
    @0xSEGFAULT Glad to have helped. If this solved your problem, you could mark it as accepted.
  • Kusalananda
    Kusalananda almost 6 years
    Note that since every expansion is unquoted in this code, the shell will perform word splitting and filename globbing on everything.