Soru Bash komut dosyasındaki bir dosyaya nasıl heredoc yazabilirim?


Bash komut dosyasında buraya bir belgeyi nasıl yazabilirim?


539
2018-06-01 20:28


Menşei


Ayrıca bakınız stackoverflow.com/questions/22697688/... - tripleee


Cevaplar:


Gelişmiş Bash-Scripting Kılavuzunu okuyun Bölüm 19. Burada Belgeler.

İçeriği bir dosyaya yazacak bir örnek aşağıdadır. /tmp/yourfilehere

cat << EOF > /tmp/yourfilehere
These contents will be written to the file.
        This line is indented.
EOF

Son 'EOF' ( LimitString) kelimenin önünde herhangi bir boşluk olmamalıdır, çünkü LimitString tanınmayacak.

Bir kabuk senaryosunda, kodu okunabilir hale getirmek için girinti kullanmak isteyebilirsiniz, ancak bu, buradaki belgenin içindeki metni girmenin istenmeyen etkisine sahip olabilir. Bu durumda <<- önde gelen sekmeleri devre dışı bırakmak için (bir çizgi izler)Not Bunu test etmek için ihtiyacınız olacak önde gelen boşlukları sekme karakteri ile değiştirin, burada gerçek sekme karakterlerini yazdıramam.)

#!/usr/bin/env bash

if true ; then
    cat <<- EOF > /tmp/yourfilehere
    The leading tab is ignored.
    EOF
fi

Metin içerisindeki değişkenleri yorumlamak istemiyorsanız, tek tırnak işaretleri kullanın:

cat << 'EOF' > /tmp/yourfilehere
The variable $FOO will not be interpreted.
EOF

Heredoc'u bir komut boru hattından geçirmek için:

cat <<'EOF' |  sed 's/a/b/'
foo
bar
baz
EOF

Çıktı:

foo
bbr
bbz

... veya heredoc'i bir dosyaya yazmak sudo:

cat <<'EOF' |  sed 's/a/b/' | sudo tee /etc/config_file.conf
foo
bar
baz
EOF

758
2018-06-02 03:40



Bash'e bile ihtiyacınız yok, bu özellik de Bourne / Korn / POSIX kabuklarında. - Janus Troelsen
ne dersin <<<, onları nasıl çağırıyorlar? - Jürgen Paul
@PineappleUndertheSea <<< 'Burada Dizeler' denir. Kod gibi tr a-z A-Z <<< 'one two three' dize ile sonuçlanacak ONE TWO THREE. Daha fazla bilgi en.wikipedia.org/wiki/Here_document#Here_strings - Stefan Lasiewski
Son EOF herhangi bir boşluk içermemelidir sonra ya. En azından bash, bu, sınırlayıcı olarak tanınmamasına neden olur. - carpii
Bu özel heredocun, ikame içerenler yerine, tam anlamıyla bir içerik olması amaçlandığından, <<'EOF' ziyade <<EOF. - Charles Duffy


Kullanmak yerine cat ve G / Ç yönlendirme kullanmak yararlı olabilir tee yerine:

tee newfile <<EOF
line 1
line 2
line 3
EOF

Daha özlü, artı yönlendirme operatörü aksine kombine edilebilir sudo kök izinli dosyalara yazmanız gerekiyorsa.


109
2018-06-13 17:35



Eklemeyi öneririm > /dev/null İlk satırın sonunda, burada oluşturulduğu zaman stdout olarak görüntülenen dosyanın içeriğini önlemek için. - Joe Carroll
Güzel, teşekkürler! Her ne kadar bu kullanımdaki bazı eksiklikleri ortadan kaldırıyor olsa da tee ilk etapta sanırım. - Livven
Doğru, ancak çözümünüz, onun uyumluluğundan dolayı bana hitap etti sudokısalığı nedeniyle değil, :-) - Joe Carroll
@MountainX Çıkış man tee. Kullan -a üzerine yazmak yerine eklemek için bayrak. - Livven
Bazen denetlemek zorunda olduğum bir config betiğinde kullanmak için bunu daha çok seviyorum Çünkü İçeriği yazdırır. - Alois Mahdal


Not:

Soru (burada bir belge nasıl yazılır (aka) heredoc(bash betikindeki bir dosyaya?)) (en az) 3 ana bağımsız boyuta veya alt soruna sahiptir:

  1. Varolan bir dosyanın üzerine yazmak, varolan bir dosyaya eklemek mi yoksa yeni bir dosyaya mı yazmak istiyorsunuz?
  2. Kullanıcınız veya başka bir kullanıcı (ör. root) dosya sahibi?
  3. Heredocunuzun içeriğini tam anlamıyla yazmak veya heredokuzun içinde değişken referansları yorumlamak mı istiyorsunuz?

(Önemli görmediğim diğer boyutlar / alt sorular var. Bunları eklemek için bu cevabı düzenlemeyi düşünün!) Yukarıda listelenen sorunun boyutlarının, farklı sınırlayıcı tanımlayıcılarla daha önemli kombinasyonlarından bazılarıdır. hakkında kutsal EOFsadece sınırlayıcı tanımlayıcınız olarak kullandığınız dizenin doğru olduğundan emin olun. değil Heredocunuzda oluşur:

  1. Sahip olduğunuz varolan bir dosyanın (veya yeni bir dosyaya yazın) üzerine yazmak için, değişkenler heredoc içinde yer alır:

    cat << EOF > /path/to/your/file
    This line will write to the file.
    ${THIS} will also write to the file, with the variable contents substituted.
    EOF
    
  2. Sahip olduğunuz varolan bir dosyayı (veya yeni bir dosyaya yazın), heredoc içinde değişken referansların yerini almak için:

    cat << FOE >> /path/to/your/file
    This line will write to the file.
    ${THIS} will also write to the file, with the variable contents substituted.
    FOE
    
  3. Sahip olduğunuz varolan bir dosyanın (ya da yeni bir dosyaya yaz), heredoc'un değişmez içeriği ile üzerine yazmak için:

    cat << 'END_OF_FILE' > /path/to/your/file
    This line will write to the file.
    ${THIS} will also write to the file, without the variable contents substituted.
    END_OF_FILE
    
  4. Sahip olduğunuz varolan bir dosyayı (veya yeni bir dosyaya), heredoc'un değişmez içeriği ile eklemek için:

    cat << 'eof' >> /path/to/your/file
    This line will write to the file.
    ${THIS} will also write to the file, without the variable contents substituted.
    eof
    
  5. Köküne ait varolan bir dosyanın (veya yeni bir dosyaya yazılmasının), heredoc'un içindeki değişken referansların değiştirilmesi:

    cat << until_it_ends | sudo tee /path/to/your/file
    This line will write to the file.
    ${THIS} will also write to the file, with the variable contents substituted.
    until_it_ends
    
  6. Heredoc'un hazır içeriği ile kullanıcı = foo'ya ait mevcut bir dosyayı (veya yeni bir dosyaya yaz) eklemek için:

    cat << 'Screw_you_Foo' | sudo -u foo tee -a /path/to/your/file
    This line will write to the file.
    ${THIS} will also write to the file, without the variable contents substituted.
    Screw_you_Foo
    

38
2017-09-18 03:11



# 6 en iyisidir. Ancak # 6 ile mevcut dosyanın içeriğini nasıl yazıyorsunuz? - Aleksandr Makov
@Aleksandr Makov: # 6 ile mevcut dosyanın içeriğini nasıl yazıyorsunuz? İhmal et -a == --append; diğer bir deyişle, tee -a -> tee. Görmek info tee (Buraya alıntı yaparım, ancak yorum işaretlemesi çok sınırlıdır. - TomRoche
# 6'ya kedi ve pipet kullanarak tee yerine faydası var mı sudo tee /path/to/your/file << 'Screw_you_Foo'? - codemonkee
Niye ya FOE yerine EOF ek örnekte? - becko


@ Livven'in üzerine inşa etmek Cevapİşte bazı yararlı kombinasyonlar.

  1. değişken ikame, önde gelen sekme, dosya üzerine yaz, stdout'a eko

    tee /path/to/file <<EOF
    ${variable}
    EOF
    
  2. değişken ikamesi yokönde gelen sekme, dosya üzerine yaz, stdout'a eko

    tee /path/to/file <<'EOF'
    ${variable}
    EOF
    
  3. değişken ikame önde gelen sekme kaldırıldı, dosyanın üzerine yaz, stdout'a eko

    tee /path/to/file <<-EOF
        ${variable}
    EOF
    
  4. değişken ikame, lider sekme korunur, dosyaya ekle, stdout'a eko

    tee -a /path/to/file <<EOF
    ${variable}
    EOF
    
  5. değişken ikame, önde gelen sekme, dosya üzerine yaz, stdout'a eko yok

    tee /path/to/file <<EOF >/dev/null
    ${variable}
    EOF
    
  6. yukarıdaki ile kombine edilebilir sudo de

    sudo -u USER tee /path/to/file <<EOF
    ${variable}
    EOF
    

14
2017-08-02 21:48





Bu soruna sahip olabilecek gelecekteki insanlar için aşağıdaki format işe yaradı:

(cat <<- _EOF_
        LogFile /var/log/clamd.log
        LogTime yes
        DatabaseDirectory /var/lib/clamav
        LocalSocket /tmp/clamd.socket
        TCPAddr 127.0.0.1
        SelfCheck 1020
        ScanPDF yes
        _EOF_
) > /etc/clamd.conf

12
2018-06-01 21:02



Parantezlere gerek yok: cat << END > afile ardından heredoc iyi çalışır. - glenn jackman
Teşekkürler, bu aslında karşılaştığım başka bir sorunu çözdü. Birkaç doktordan sonra bazı sorunlar vardı. Yukarıdaki tavsiyede olduğu gibi, parens ile yapmak zorunda olduğunu düşünüyorum. - Joshua Enfield
Bu işe yaramaz. Çıkış yönlendirmesi ile başlayan satırın sonunda olması gerekir. cat kabul edilen cevapta gösterildiği gibi. - Dennis Williamson
@DennisWilliamson Çalışır, bu parens için ne. Bütün cat bir subshell içinde çalışır ve subshell tüm çıktı dosyasına yönlendirilir - Izkata
@Izkata: Bu cevabın düzenleme geçmişine bakarsanız, yorumumu yapmadan ve daha sonra tekrar eklemeden önce parantezler kaldırılmıştır. glenn jackman (ve benim) yorum geçerlidir. - Dennis Williamson


Kök izinleri gerektiğinde

Hedef dosya için kök izinleri gerektiğinde, |sudo tee yerine >:

cat << 'EOF' |sudo tee /tmp/yourprotectedfilehere
The variable $FOO will *not* be interpreted.
EOF

12
2018-02-13 20:55



Değişkenleri buraya dökmek mümkün mü? Nasıl FOO $ yorumlandı? - user1527227
@ user1527227 Burada örnek olarak dosya diyor: Değişken $ FOO olacak değil yorumlanabilir. - Serge Stroobandt
Altında Bu cevabı bir araya getirme ve organize etme girişiminde bulundum. Stefan Lasiewski. - TomRoche
@ user1527227 Sadece EOF'u tek tırnak içine almayın. Sonra $ FOO yorumlanacaktır. - imnd_neel


Örneğin bunu kullanabilirsiniz:

İlk (ssh bağlantısı yapmak):

while read pass port user ip files directs; do
    sshpass -p$pass scp -o 'StrictHostKeyChecking no' -P $port $files $user@$ip:$directs
done <<____HERE
    PASS    PORT    USER    IP    FILES    DIRECTS
      .      .       .       .      .         .
      .      .       .       .      .         .
      .      .       .       .      .         .
    PASS    PORT    USER    IP    FILES    DIRECTS
____HERE

İkincisi (komutları yürütmek):

while read pass port user ip; do
    sshpass -p$pass ssh -p $port $user@$ip <<ENDSSH1
    COMMAND 1
    .
    .
    .
    COMMAND n
ENDSSH1
done <<____HERE
    PASS    PORT    USER    IP
      .      .       .       .
      .      .       .       .
      .      .       .       .
    PASS    PORT    USER    IP    
____HERE

Üçüncü (komutları yürütme):

Script=$'
#Your commands
'

while read pass port user ip; do
    sshpass -p$pass ssh -o 'StrictHostKeyChecking no' -p $port $user@$ip "$Script"

done <<___HERE
PASS    PORT    USER    IP
  .      .       .       .
  .      .       .       .
  .      .       .       .
PASS    PORT    USER    IP  
___HERE

İleri (değişkenleri kullanarak):

while read pass port user ip fileoutput; do
    sshpass -p$pass ssh -o 'StrictHostKeyChecking no' -p $port $user@$ip fileinput=$fileinput 'bash -s'<<ENDSSH1
    #Your command > $fileinput
    #Your command > $fileinput
ENDSSH1
done <<____HERE
    PASS    PORT    USER    IP      FILE-OUTPUT
      .      .       .       .          .
      .      .       .       .          .
      .      .       .       .          .
    PASS    PORT    USER    IP      FILE-OUTPUT
____HERE

2
2018-02-16 10:17