I have the file ~/nginx_app containing this conf template:

server {
    root /var/www/html/${domain}/;
    server_name ${domain} www.${domain};

I also have this script:

domain="$1" && test -z ${domain} && return
cat ~/myAddons/nginx_app > /etc/sites-available/${domain}.conf

As you can see, I desire to redirect the content of nginx_app into ${domain}.conf, which the script creates based on the template.

Now, need the variables inside the template to be expanded, when their cat redirection takes place. How would you promise that expansion does indeed take place?

I was thinking of here-string but I know it prints a string:

cat > "etc/nginx/sites-available/${domain}.conf" <<< "source ~/myAddons/nginx_app"

And also of this

cat ~/myAddons/nginx_app > etc/nginx/sites-available/${domain}.conf


After running the script, the end state should /etc/sites-available/example.com.conf:

server {
    root /var/www/html/example.com/;
    server_name example.com www.example.com;
  • You said, "I need the variables inside ~/nginx_app to be expanded". Well, if I understand correctly, you want shell script (or basically the shell that runs the script) to read ~/myAddons/nginx_app file, interpret variables, and perform replacement of variable names in the other contents of the same file, and write the result to new file. Can you make a simple example of input file with mock variables and what you desire output file to look like ? – Sergiy Kolodyazhnyy Feb 5 '18 at 5:21
  • @SergiyKolodyazhnyy I've edited the question generally and also added an example of the desired end state. – user9303970 Feb 5 '18 at 5:32

What you wanna do is basically string replacement to process contents of input file, not variable expansion (although that does get performed by the shell when you reference the variable, but that's not what does the job on input contents).

That can be done with sed, and shell variable there can be used, although consult this answer for possible issues.

test -n "$1" || exit 1
sed 's/\${domain}/'"$1"'/g' input.txt > output_"$1".txt

Adjust input and output accordingly. Note also that I use $1 positional parameter directly, instead of copying that to variable.

If I may so suggest better approach would be to have a script which acts as template, and you only provide variables on as positional parameters to script command-line or otherwise via sourcing a variables file. Copying file and performing acrobatics with replacing strings, especially if patterns get complex, is not the best approach.


What I got working (edited per StephenHarris comment) is:

domain=aa ; sed s"/\$domain/$domain/" ~/nginx_app >> ${domain}.conf

The second $domain of the sed command expands into aa in my test case. However, since the first $domain has its $ identifier escaped, it is NOT expanded.

There exists another command-line program called awk which has a more powerful way of passing variables from outside it to inside it, but sed is considered faster and more efficient (not sure if really true nowadays), so that's why I answered with sed because this was a simple case. In awk, you could use:

awk -v domain=aa '{gsub("\\$domain",domain);print}' ~/nginx_app >> ${domain}.conf

Here, the -v option to awk defines an awk variable, and gsub is an awk function for performing a global substitution for a given line. The escapinng sequence \\ is slightly longer than for the sed solution.

  • The code block is up to you, but probably avoid things like "mark the answer as accepted"; it's nothing to do with the actual answer – Michael Mrozek Feb 5 '18 at 5:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.