Search code examples
linuxbashshellunix

Forcing bash to expand variables in a string loaded from a file


I am trying to work out how to make bash (force?) expand variables in a string (which was loaded from a file).

I have a file called "something.txt" with the contents:

hello $FOO world

I then run

export FOO=42
echo $(cat something.txt)

this returns:

   hello $FOO world

It didn't expand $FOO even though the variable was set. I can't eval or source the file - as it will try and execute it (it isn't executable as it is - I just want the string with the variables interpolated).

Any ideas?


Solution

  • I stumbled on what I think is THE answer to this question: the envsubst command:

    echo "hello \$FOO world" > source.txt
    export FOO=42
    envsubst < source.txt
    

    This outputs: hello 42 world

    If you would like to continue work on the data in a file destination.txt, push this back to a file like this:

    envsubst < source.txt > destination.txt
    

    In case it's not already available in your distro, it's in the GNU package gettext.

    @Rockallite

    • I wrote a little wrapper script to take care of the '$' problem.

    (BTW, there is a "feature" of envsubst, explained at https://unix.stackexchange.com/a/294400/7088 for expanding only some of the variables in the input, but I agree that escaping the exceptions is much more convenient.)

    Here's my script:

    #! /bin/bash
          ## -*-Shell-Script-*-
    CmdName=${0##*/}
    Usage="usage: $CmdName runs envsubst, but allows '\$' to  keep variables from
        being expanded.
      With option   -sl   '\$' keeps the back-slash.
      Default is to replace  '\$' with '$'
    "
    
    if [[ $1 = -h ]]  ;then echo -e >&2  "$Usage" ; exit 1 ;fi
    if [[ $1 = -sl ]] ;then  sl='\'  ; shift ;fi
    
    sed 's/\\\$/\${EnVsUbDolR}/g' |  EnVsUbDolR=$sl\$  envsubst  "$@"