mpeterson
mpeterson

Reputation: 749

Expand a variable in a variable in Bash

I have a script for which I need to pass a string which contains variables and text to conform an URI.

An example of this would be:

URI="${PROTO}://${USER}:${PASS}@${HOST}/${TARGET}"

The variables ${PROTO}, ${USER}, ${PASS}, ${HOST} and ${TARGET} are not defined when I define the variable $URI but they will be when the Bash Script is going to be executed so I need to expand URI to the final form of the string.

How can I do that? I've read eval: When You Need Another Chance but I really don't like the idea of using eval as it might be dangerous plus it means to escape a lot of parts of the URI string.

Is there another way to do it? What's the recommended solution to this problem?

Thanks M

Upvotes: 2

Views: 1311

Answers (2)

Doug
Doug

Reputation: 3863

Before executing the script, define the variables using 'export'.

export PROTO='http'
export USER='bob'
export PASS='password'
export HOST='myhostname'
export TARGET='index.html'

bash ./myscript_with_uri.sh

OR

Create the URI script as a procedure that will return the URI.

uri_creater.sh

makeUri ()
{
    URI="${PROTO}://${USER}:${PASS}@${HOST}/${TARGET}
}

script_using_uri.sh

. uri_creater.sh
PROTO='http'
USER='bob'
PASS='password'
HOST='myhostname'
TARGET='index.html'

makeUri

url="${URI}"

echo "${url}"

Tested on Centos 6.5 with bash.

Upvotes: 3

chepner
chepner

Reputation: 530920

A variable stores data; if you don't have values for PROTO et al. yet, then you don't have data. You need a template.

uri_template="%s://%s:%s@%s/%s"

Later, when you do have the rest of the data, you can plug them into the template.

uri=$(printf "$uri_template" "$PROTO" "$USER" "$PASS" "$HOST" "$TARGET")

(In bash, you can avoid the fork from the command substitution by using the -v option: printf -v uri "$uri_template" "$PROTO" "$USER" "$PASS" "$HOST" "$TARGET".)

You can also define a function:

uri () {
    # I'm being lazy and assuming uri will be called with the correct 5 arguments
    printf "%s://%s:%s@%s/%s" "$@"
}

# Variables and functions exist in separate namespaces, so the following works
uri=$(uri "$PROMPT" "$USER" "$PASS" "$HOST" "$TARGET")

Upvotes: 3

Related Questions