web-dev-qa-db-fra.com

Comment puis-je écrire un heredoc dans un fichier en script Bash?

Comment puis-je écrire un document here dans un fichier en script Bash?

654
Joshua Enfield

Lisez le Guide avancé de script de bash Chapitre 19. Ici les documents .

Voici un exemple qui va écrire le contenu dans un fichier à /tmp/yourfilehere

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

Notez que le dernier 'EOF' (LimitString) ne doit avoir aucun espace devant le mot, car cela signifie que le LimitString ne sera pas reconnu.

Dans un script Shell, vous pouvez utiliser l'indentation pour rendre le code lisible, mais cela peut avoir pour effet indésirable d'indenter le texte dans votre document here. Dans ce cas, utilisez <<- (suivi d'un tiret) pour désactiver les tabulations en tête (. Notez que pour tester cela, vous devez remplacez les espaces blancs par un caractère de tabulation , car je ne peux pas imprimer les caractères de tabulation réels ici.)

#!/usr/bin/env bash

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

Si vous ne voulez pas interpréter les variables dans le texte, utilisez des guillemets simples:

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

Pour diriger l'hérédoc via un pipeline de commande:

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

Sortie:

foo
bbr
bbz

... ou écrire le heredoc dans un fichier en utilisant Sudo:

cat <<'EOF' |  sed 's/a/b/' | Sudo tee /etc/config_file.conf
foo
bar
baz
EOF
916
Stefan Lasiewski

Au lieu d'utiliser cat et la redirection E/S, il peut être utile d'utiliser tee à la place:

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

Il est plus concis et, contrairement à l'opérateur de redirection, il peut être combiné à Sudo si vous devez écrire dans des fichiers avec des droits root.

124
Livven

Note:

La question (comment écrire un document ici (aka heredoc ) dans un fichier dans un script bash?) A (au moins) 3 dimensions ou sous-questions principales indépendantes:

  1. Voulez-vous écraser un fichier existant, l'ajouter à un fichier existant ou écrire dans un nouveau fichier?
  2. Votre utilisateur ou un autre utilisateur (par exemple, rootname__) est-il propriétaire du fichier?
  3. Voulez-vous écrire littéralement le contenu de votre heredoc ou laisser bash interpréter les références de variable à l'intérieur de votre heredoc?

(Il y a d'autres dimensions/sous-questions que je ne considère pas comme importantes. Pensez à modifier cette réponse pour les ajouter!) Voici certaines des combinaisons les plus importantes des dimensions de la question répertoriée ci-dessus, avec différents identificateurs de délimitation différents - rien sacré à propos de EOFname__, assurez-vous simplement que la chaîne que vous utilisez comme identifiant de délimitation ne se trouve pas not ​​dans votre heredoc:

  1. Pour écraser un fichier existant (ou écrire dans un nouveau fichier) que vous possédez, en substituant des références de variable à l'intérieur du heredoc:

    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. Pour ajouter un fichier existant (ou écrire dans un nouveau fichier) que vous possédez, en substituant des références de variable à l'intérieur de l'hérédoc:

    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. Pour écraser un fichier existant (ou écrire dans un nouveau fichier) que vous possédez, avec le contenu littéral de heredoc:

    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. Pour ajouter un fichier existant (ou écrire dans un nouveau fichier) que vous possédez, avec le contenu littéral de heredoc:

    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. Pour écraser un fichier existant (ou écrire dans un nouveau fichier) appartenant à root, en remplaçant les références de variable à l'intérieur du heredoc:

    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. Pour ajouter un fichier existant (ou écrire dans un nouveau fichier) appartenant à user = foo, avec le contenu littéral de heredoc:

    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
    
50
TomRoche

Pour construire sur @ Livven answer , voici quelques combinaisons utiles.

  1. substitution de variable, onglet principal conservé, fichier de remplacement, echo to stdout

    tee /path/to/file <<EOF
    ${variable}
    EOF
    
  2. pas de substitution de variable , onglet sélectionné conservé, fichier écrasé, écho vers stdout

    tee /path/to/file <<'EOF'
    ${variable}
    EOF
    
  3. substitution de variable, onglet principal supprimé , écrasement du fichier, écho vers stdout

    tee /path/to/file <<-EOF
        ${variable}
    EOF
    
  4. substitution de variable, onglet principal conservé, ajout au fichier , echo to stdout

    tee -a /path/to/file <<EOF
    ${variable}
    EOF
    
  5. substitution de variable, onglet principal conservé, fichier de remplacement, pas d'écho sur la sortie standard

    tee /path/to/file <<EOF >/dev/null
    ${variable}
    EOF
    
  6. ce qui précède peut également être combiné avec Sudo

    Sudo -u USER tee /path/to/file <<EOF
    ${variable}
    EOF
    
29
go2null

Quand les autorisations root sont nécessaires

Lorsque des autorisations root sont requises pour le fichier de destination, utilisez |Sudo tee au lieu de >:

cat << 'EOF' |Sudo tee /tmp/yourprotectedfilehere
The variable $FOO will *not* be interpreted.
EOF
15
Serge Stroobandt

Pour les personnes futures susceptibles d’avoir ce problème, le format suivant a fonctionné:

(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
11
Joshua Enfield

Comme exemple, vous pouvez l'utiliser:

First (établissement d'une connexion ssh):

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

Deuxième (commandes en cours d'exécution):

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

Troisième (commandes en cours d'exécution):

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

Forth (en utilisant des variables):

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
MLSC

J'aime cette méthode de concision, de lisibilité et de présentation dans un script en retrait:

<<-End_of_file >file
→       foo bar
End_of_file

→        est un tab personnage.

0
daniel Azuelos