Domanda

Ho un file di testo scheletro con stringhe segnaposto:

blah blah blah
blah $PLACEHOLDER_1$
blah
$PLACEHOLDER_2$

e così via. Modulo "specifico" dei segnaposto non ha importanza, posso cambiarli nel modo più comodo per un'implementazione specifica.

Ho uno script bash in cui conosco i valori per i segnaposto e devo generare un nuovo file, con i segnaposto sostituiti con i valori.

#! /bin/sh
PLACEHOLDER_1 = 'string 1'
PLACEHOLDER_2 = 'multiline 
string 
2'
# TODO: Generate file output.txt from file output.template 
#       using placeholders above.

Posso farlo in più passaggi con sed, ma non è divertente. Voglio non usare Perl. Voglio usare textutils e bash solo se stesso.

Qual è il modo migliore per fare ciò che voglio in un unico passaggio?

È stato utile?

Soluzione

Puoi ancora usare sed per eseguire la sostituzione in un unico passaggio. Devi solo specificare tutti i ricambi in un solo comando.

ad es.

sed -i 's/PLACEHOLDER_1/string 1/g;s/PLACEHOLDER_2/string 2/g' <file>

Altri suggerimenti

Ecco un modo per farlo senza sed:

Innanzitutto, un file modello leggermente modificato in cui i segnaposto sono variabili bash:

blah blah blah
blah $PLACEHOLDER_1
blah
$PLACEHOLDER_2

E lo script:

#! /bin/sh
templatefile=output.template
outputfile=output.txt

PLACEHOLDER_1='string 1'

PLACEHOLDER_2='multiline 
string 
2'

# DONE: Generate file output.txt from file output.template 
#       using placeholders above.

echo "$(eval "echo \"$(cat $templatefile)\"")" > $outputfile

Ecco una versione che mostra un modello contenuto nello script, ma con una svolta. Dimostra anche i valori predefiniti, che possono essere utilizzati anche nella versione del file modello, inoltre puoi fare matematica nel modello:

#! /bin/sh
template='blah blah blah
blah $PLACEHOLDER_1
blah
${PLACEHOLDER_2:-"some text"} blah ${PLACEHOLDER_3:-"some
lines
of
text"} and the total is: $((${VAL_1:-0} + ${VAL_2:-0}))'
# default operands to zero (or 1) to prevent errors due to unset variables
outputfile=output.txt

# gears spin, bells ding, values for placeholders are computed

PLACEHOLDER_1='string 1'

PLACEHOLDER_2='multiline 
string 
2'

VAL_1=2

VAL_2=4

unset PLACEHOLDER_3 # so we can trigger one of the defaults

# Generate file output.txt from variable $template 
#       using placeholders above.

echo "$(eval "echo \"$template\"")" > $outputfile

Niente sed, niente loop, solo annidamenti e virgolette pelose. Sono abbastanza sicuro che tutte le citazioni ti proteggeranno da cose dannose in un file modello, ma non lo garantirò.

Basandoti sulla risposta precedente, forse usa un array e calcola la stringa sed?

#!/bin/sh
PLACEHOLDER[0]='string 1'
PLACEHOLDER[1]='multiline 
string 
2'

s="sed -i "
for(( i=0 ; i<${#PLACEHOLDER[*]} ; i++ )) ; do 
    echo ${PLACEHOLDER[$i]}
    s=$s"s/PLACEHOLDER_$i/${PLACEHOLDER[$i]}/g;"
done
echo $s

Sembra fallire nelle stringhe multilinea, tuttavia.

Non so quanto possano essere portatili gli array Bash. Snippet sopra testato con " GNU bash, versione 3.2.17 (1) -release (i386-apple-darwin9.0) "

La mia unica soluzione bash:

TEMPLATE='
foo
$var1
bar
$var2'
eval "echo \"$TEMPLATE\""

Mi sono appena imbattuto in questa domanda perché stavo cercando esattamente lo stesso e ho trovato envsubst (1) .

Puoi usare envsubst se non ti dispiace usare le variabili d'ambiente:

PLACEHOLDER_1='string 1' PLACEHOLDER_2='multiline 
string 
2' envsubst < output.template 

Se hai molte variabili puoi memorizzarle in un file e solo source (ricorda di usare export alla fine del file di provenienza!)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top