Utilizzo di variabili all'interno di una eredità bash


192

Sto cercando di interpolare le variabili all'interno di una eredità bash:

var=$1
sudo tee "/path/to/outfile" > /dev/null << "EOF"
Some text that contains my $var
EOF

Questo non funziona come mi aspetterei ( $varviene trattato alla lettera, non espanso).

Devo usare sudo teeperché la creazione del file richiede sudo. Fare qualcosa del tipo:

sudo cat > /path/to/outfile <<EOT
my text...
EOT

Non funziona, perché >outfileapre il file nella shell corrente, che non utilizza sudo.


9
Questa è una confusione comprensibile! Come indicato di seguito, la citazione di qualsiasi parte del delimitatore disattiva l'espansione nell'ereditarietà (come se fosse in ''), ma non la citazione del delimitatore attiva l'espansione (come se fosse in ""). Tuttavia, la tua intuizione è corretta in Perl, dove un ereditario con identificatore a virgoletta singola si comporta come se fosse tra virgolette singole, uno con un identificatore tra virgolette doppie come se fosse tra virgolette doppie e uno con identificatore con segno di spunta indietro come in backtick ! Vedi: perlop: << EOF
Nils von Barth,

Risposte:


252

In risposta alla tua prima domanda, non c'è sostituzione di parametri perché hai inserito il delimitatore tra virgolette - il manuale di bash dice :

Il formato dei documenti qui è:

      <<[-]word
              here-document
      delimiter

Nessuna espansione di parametro, sostituzione di comando, espansione aritmetica o espansione del percorso viene eseguita su word . Se vengono citati caratteri in una parola , il delimitatore è il risultato della rimozione della citazione in una parola e le righe nel documento qui non vengono espanse. Se la parola non è quotata, tutte le righe del documento qui sono soggette all'espansione dei parametri, alla sostituzione dei comandi e all'espansione aritmetica. [...]

Se cambi il tuo primo esempio da usare al <<EOFposto di << "EOF"troverai che funziona.

Nel tuo secondo esempio, la shell invoca sudosolo con il parametro cate il reindirizzamento si applica all'output di sudo catcome utente originale. Funzionerà se provi:

sudo sh -c "cat > /path/to/outfile" <<EOT
my text...
EOT

Se sei interessato, puoi anche farlo come: (cat > /path/to/outfile) <<EOFal posto delsudo sh -c ... <<EOF
Voltaire,

Per favore, dimmi se sepolto a Bash è una buona ragione per cui è così.
Landon Kuhn,

96

Non utilizzare le virgolette con <<EOF:

var=$1
sudo tee "/path/to/outfile" > /dev/null <<EOF
Some text that contains my $var
EOF

L'espansione delle variabili è il comportamento predefinito all'interno di here-docs. Si disabilita quel comportamento citando l'etichetta (con virgolette singole o doppie).


36

Come corollario tardivo delle risposte precedenti qui, probabilmente finisci in situazioni in cui vuoi interpolare alcune ma non tutte le variabili. Puoi risolverlo usando le barre rovesciate per sfuggire ai segni del dollaro e alle levette; oppure puoi inserire il testo statico in una variabile.

Name='Rich Ba$tard'
dough='$$$dollars$$$'
cat <<____HERE
$Name, you can win a lot of $dough this week!
Notice that \`backticks' need escaping if you want
literal text, not `pwd`, just like in variables like
\$HOME (current value: $HOME)
____HERE

Demo: https://ideone.com/rMF2XA

Nota che uno qualsiasi dei meccanismi di quotazione - \____HEREo "____HERE"o '____HERE'- disabiliterà tutta l'interpolazione variabile e trasformerà il documento qui in un pezzo di testo letterale.

Un'attività comune è combinare le variabili locali con lo script che dovrebbero essere valutati da una shell, un linguaggio di programmazione o un host remoto diversi.

local=$(uname)
ssh -t remote <<:
    echo "$local is the value from the host which ran the ssh command"
    # Prevent here doc from expanding locally; remote won't see backslash
    remote=\$(uname)
    # Same here
    echo "\$remote is the value from the host we ssh:ed to"
:

3
Non sono sicuro del motivo per cui questo è stato votato in negativo, ma aggiunge una nota valida che non è inclusa nella risposta ora più votata.
Inian,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.