Setting a variable whose value depends on another variable
Solution 1
The primary thing to note is that you probably don't need to export these variables; that necessity is reserved only when when a subprocess is querying its inherited environment for a variable. Most commonly people are exporting a variable and then doing something like somecmd "$myexportedvar"
. Your shell is expanding $myexportedvar
before somecmd
ever sees it.
If you really do need to export these for a subprocess to pull from its environment:
while IFS= read -r line; do
if [[ $line == *=* && $line != #* ]]; then
IFS== read -r var val <<<"$line"
printf -v "$var" '%s' "$val"
export "$var"
fi
done < "$HOME/variables.txt"
this loop checks that the line is an assignment (kinda) and that the first character is not a comment hash. makes the effort a little more robust, but just barely. see the two options below instead, for handling this more carefully.
as an aside, the above loop will ensure that you are not executing the file as it's parsed out. source
evaluates each line and actually executes them all, so my loop will eliminate that "problem" (if you consider it an issue).
Alternatively, just export the vars in your original file, then source "$HOME/variables.txt"
and the work is already done.
you may want to just use set -a; . "$HOME"/variables.txt; set +a
. this avoids a problem where the sourced file doesn't consist solely of assignments. the parsing loop above can result in false-positives. read help set
to understand what it's doing.
Also, Don't Read Lines With For and Use More Quotes
Solution 2
you have a easier way to perform that.
cat vars
host=/srv/www/vhosts/hosting
index=$host/index.php
my test script:
#!/bin/bash
. ./vars
echo $host
echo $index
Execution
./printvars.sh
/srv/www/vhosts/hosting
/srv/www/vhosts/hosting/index.php
Basically the . ./vars executes the files and loads the variables.
Solution 3
My advice would also be to source the file and export everything within the "variables.txt" file. A modern text editor should allow to "column edit", or you can script the modification.
However, I managed to answer your question with this script :
#!/bin/sh
f=./variables.txt
source ${f}
for vname in $(cut -f1 -d'=' ${f})
do
export ${vname}
done
The difference is that I source the variables.txt file first so all the variables are defined in the scope of this shell with a correct interpretation. Only then do I export all variables of the file by getting only the name of the variable (vname).
On a side note, you should protect your variables with ${}.
Related videos on Youtube
easl
Updated on September 18, 2022Comments
-
easl over 1 year
i have a text file variables.txt where i store my variables
host=/srv/www/vhosts/hosting
index=$host/index.php
as you see the second variables depends on the first one.
i also have a script file to load these variables
f=~/variables.txt for line in $(cat $f) do export $line done
when i execute the script file, my first variable gets loaded, while the second doesn't:
bash: $host/index.php: No such file or directory
it's because after loading the first variable host, it doesn't remember its value to use for setting the second variable index.
So how to solve this problem? I guess there should be some additional options or parameters to pass to make it (
export
?) remember the set variable value in afor
loop. -
easl almost 11 yearsi know, but my actual file is too big and filled up with variable definitions, that i want to
export
with afor
loop. i don't want to writeexport
command on each line in my variables.txt file and then to source it, i want to do it withfor
loop instead. -
msw almost 11 yearsThe command
sed 's/^/export /' vars
writes "export" at the beginning of each line in vars. This is unix, you're trying to do it the hard way. -
Josh McGee almost 11 yearsas an aside to your aside, one should only use curly braces for two things: disambiguation between a variable's name and other coinjoined text
"${var}string"
, and alternatively for Parameter Expansions"${name:-default}"
. "Protecting" variables is to be done with double-quotes. Use More Quotes