Bash heredoc içindeki değişkenleri kullanma


192

Bir bash heredoc içinde değişkenleri enterpolasyon çalışıyorum:

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

Bu beklediğim gibi çalışmıyor ( $vartam anlamıyla tedavi, değil genişletilmiş).

sudo teeDosya oluşturmak sudo gerektirdiğinden kullanmam gerekiyor . Gibi bir şey yapmak:

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

Sudo >outfilekullanılmayan dosyayı geçerli kabukta açar , çünkü çalışmaz .


9
Bu anlaşılabilir bir karışıklık! (Bu sanki bir yorumlu metin genişleme kapalı sınırlayıcı dönüşler herhangi bir bölümünü alıntı aşağıda belirtildiği gibi ''), ancak değil (o sanki üzerinde sınırlayıcı dönüşler genişleme alıntı ""). Bununla birlikte, sezginiz, tek tırnaklı tanımlayıcıya sahip bir heredoc'un tek tırnak içindeymış gibi davrandığı Perl'de doğrudur, biri çift tırnaklı gibi çift tırnaklı bir tanıtıcıya ve backticks'te olduğu gibi geri işaretli tanımlayıcıya sahip ! Bkz: perlop: << EOF
Nils von Barth

Yanıtlar:


252

İlk sorunuza yanıt olarak, sınırlayıcıyı tırnak içine aldığınız için parametre ikamesi yoktur - bash kılavuzu diyor :

Buradaki belgelerin formatı:

      <<[-]word
              here-document
      delimiter

Sözcük üzerinde parametre genişletmesi, komut değiştirme, aritmetik genişletme veya yol adı genişletmesi gerçekleştirilmez . Sözcükteki herhangi bir karakter tırnak içine alınmışsa, ayırıcı sözcük üzerinde tırnak işareti kaldırmanın sonucudur ve bu belgedeki satırlar genişletilmez. Eğer kelime tırnak içine almaktadır, burada-belgenin tüm hatlar parametre genişleme, komut ikamesi ve aritmetik yorumlama tabi tutulur. [...]

İlk örneğinizi kullanmak <<EOFyerine değiştirirseniz << "EOF"bunun işe yaradığını göreceksiniz.

İkinci örneğinizde, kabuk sudoyalnızca parametre ile çağrılır catve yönlendirme sudo cat, orijinal kullanıcı olarak çıktıya uygulanır . Eğer denerseniz çalışır:

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

Eğer ilgileniyorsanız bunu da yapabilirsiniz: (cat > /path/to/outfile) <<EOFyerinesudo sh -c ... <<EOF
Voltaire

Lütfen bana Bash'e gömüldüğünü söyle, bunun böyle olmasının iyi bir nedeni.
Landon Kuhn

96

Şununla tırnak işareti kullanmayın <<EOF:

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

Değişken genişletme, bu belgelerin içindeki varsayılan davranıştır. Bu davranışı, etiketi (tek veya çift tırnak işaretleri ile) vererek alıntılayabilirsiniz.


36

Buradaki önceki yanıtların geç bir sonucu olarak, muhtemelen tüm değişkenlerin değil, bazılarının enterpolasyonu olmasını istediğiniz durumlar ile sonuçlanırsınız . Dolar işareti ve backticks kaçmak için ters eğik çizgiler kullanarak bunu çözebilir; veya statik metni bir değişkene koyabilirsiniz.

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

Alıntılama mekanizmalarından herhangi birinin - \____HEREveya "____HERE"veya '____HERE'- tüm değişken enterpolasyonunu devre dışı bırakacağını ve buradaki belgeyi gerçek bir metne dönüştüreceğini unutmayın.

Yaygın bir görev, yerel değişkenleri farklı bir kabuk, programlama dili veya uzak ana bilgisayar tarafından değerlendirilmesi gereken komut dosyasıyla birleştirmektir.

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
Bunun neden aşağı oy verildiğinden emin değilim, ancak şimdi daha yüksek oy verilen cevapta yer almayan geçerli bir not ekliyor .
Inian
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.