Home > OS >  Bash Script - populate variable reference in a command output
Bash Script - populate variable reference in a command output

Time:12-09

This is a simplified version of the problem I'm experiencing just for demonstration purposes. But the command output when it contains a variable reference doesn't seem to go through an evaluation process to populate the variable reference it contains.

So do demonstrate I create a txt file (/mnt/external.txt) with the following line of text "${var1}/filename.txt". I then do a bash script like the following:

#!/bin/bash
var1="/home/user1"
echo $(cat /mnt/external.txt)

This then outputs "${var1}/filename.txt" rather than "/home/user1/filename.txt".

Is there a way to get it to re-evaluate the output of the cat command (just used cat to demonstrate the problem) to have it populate the variable reference with the variable value instead?

CodePudding user response:

You can invoke envsubst for all of the output of your command, which is something you mentioned in your comments but not your question.

#! /bin/bash

export MYVAR=myval

for i in {0..3}
do
    echo "$i: \$MYVAR"
done | envsubst

and the output is

0: myval
1: myval
2: myval
3: myval

CodePudding user response:

You need to pass the returned string thru eval for the substitution to take effect. Your snippet should be modified as follows:

#!/bin/bash
var1="/home/user1"
eval echo $(cat /mnt/external.txt)

CodePudding user response:

This prints what you want, but I agree with Gordon that it's not safe.

#!/usr/bin/env bash

export var1="/home/user1"
echo "$(eval "echo $(< /mnt/external.txt)")"

CodePudding user response:

You can use a heredoc to expand variables and command substitutions only:

eval "
cat <<EOF
$(</mnt/external.txt)
EOF"

Here eval is used only to print the file external.txt, so the heredoc can expand it.

This is safer and more predictable than eval "echo '$(<external.txt)'" (even with quotes). But still open to code injection if external.txt contained a command sub like $(rm important.txt), or the heredoc delimiter:

EOF
rm important.txt

The difference is that it's slightly more predictable than eval echo, where stray quotes and/or list operators (; | & etc) could cause code execution.

  • Related