Molte delle risposte utilizzando eval
e echo
tipo di lavoro, ma si rompono su varie cose, come più righe, tentativi di sfuggire ai metacaratteri della shell, fughe all'interno del modello non destinato ad essere espanso da bash, ecc.
Ho avuto lo stesso problema e ho scritto questa funzione di shell, che per quanto ne so, gestisce tutto correttamente. Ciò eliminerà comunque solo le nuove righe finali dal modello, a causa delle regole di sostituzione dei comandi di bash, ma non ho mai riscontrato che questo sia un problema fintanto che tutto il resto rimane intatto.
apply_shell_expansion() {
declare file="$1"
declare data=$(< "$file")
declare delimiter="__apply_shell_expansion_delimiter__"
declare command="cat <<$delimiter"$'\n'"$data"$'\n'"$delimiter"
eval "$command"
}
Ad esempio, puoi usarlo in questo modo con un parameters.cfg
che in realtà è uno script di shell che imposta solo variabili e un template.txt
che è un modello che usa queste variabili:
. parameters.cfg
printf "%s\n" "$(apply_shell_expansion template.txt)" > result.txt
In pratica, lo utilizzo come una sorta di sistema di template leggero.
Mi sono imbattuto in quella che penso sia LA risposta a questa domanda:il envsubst
comando:
echo "hello \$FOO world" > source.txt
export FOO=42
envsubst < source.txt
Questo restituisce:hello 42 world
Se vuoi continuare a lavorare sui dati in un file destination.txt
, riportalo in un file come questo:
envsubst < source.txt > destination.txt
Nel caso in cui non sia già disponibile nella tua distribuzione, è nel pacchetto GNU gettext
.
@Rockallite
- Ho scritto un piccolo script wrapper per occuparmi del problema '$'.
(A proposito, c'è una "caratteristica" di envsubst, spiegata su https://unix.stackexchange.com/a/294400/7088 per espandere solo alcune delle variabili nell'input, ma sono d'accordo che sfuggire alle eccezioni è molto più conveniente.)
Ecco il mio 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 "[email protected]"