Как я могу написать heredoc в файл в скрипте Bash?

Как я могу написать здесь документ в файл в сценарии Bash?

7 ответов


прочитайте руководство Advanced Bash-ScriptingГлава 19. Вот Документы.

вот пример, который будет записывать содержимое в файл по адресу /tmp/yourfilehere

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

обратите внимание, что окончательный 'EOF' (LimitString) не должно иметь пробелов перед словом, потому что это означает, что LimitString не будет распознан.

в сценарии оболочки вы можете использовать отступ, чтобы сделать код читаемым, однако это может иметь нежелательный эффект отступа текста в вашем документе here. В этом случае используйте <<- (затем тире), чтобы отключить ведущие вкладки (Примечание что для проверки этого вам нужно будет замените начальные пробелы символом табуляции, так как я не могу печатать фактические символы табуляции здесь.)

#!/usr/bin/env bash

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

если вы не хотите интерпретировать переменные в тексте, используйте одинарные кавычки:

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

передать heredoc через команду трубопровод:

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

выход:

foo
bbr
bbz

... или записать heredoc в файл с помощью sudo:

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

вместо cat и перенаправление ввода / вывода может быть полезно использовать tee вместо:

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

это более лаконично, плюс в отличие от оператора перенаправления он может быть объединен с sudo Если вам нужно записать файлы с правами root.


Примечание:

вопрос (Как написать здесь документ (он же помощи heredoc) к файлу в скрипте bash?) (по минимум) 3 основных независимых измерения или подзапросы:

  1. вы хотите перезаписать существующий файл, добавить к существующему файлу или записать в новый файл?
  2. делает ваш пользователь или другой пользователь (например,root) собственного файла?
  3. вы хотите написать содержание вашего heredoc буквально, или иметь bash интерпретировать ссылки на переменные внутри вашего heredoc?

(есть другие измерения / подзапросы, которые я не считаю важный. Подумайте о редактировании этого ответа, чтобы добавить их!) Вот некоторые из наиболее важных комбинаций измерений вопроса, перечисленных выше, с различными различными идентификаторами разграничения-нет ничего святого о EOF, просто убедитесь, что строка, которую вы используете в качестве идентификатора разделителя, делает не происходят внутри вашей heredoc:

  1. для перезаписи существующего файла (или записи в новый файл), которым вы владеете, подставляя ссылки на переменные внутри помощи 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. чтобы добавить существующий файл( или записать в новый файл), которым вы владеете, подставляя ссылки на переменные внутри heredoc:

    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. чтобы перезаписать существующий файл (или записать в новый файл), который у вас есть, с буквальным содержимым 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. чтобы добавить существующий файл (или записать в новый файл), который у вас есть, с буквальным содержимым помощи 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. чтобы перезаписать существующий файл (или записать в новый файл), принадлежащий root, подставляя ссылки на переменные внутри 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. чтобы добавить существующий файл (или записать в новый файл), принадлежащий user=foo, с буквальным содержимым 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
    

построить на @Livven это ответ, вот некоторые полезные комбинации.

  1. переменная подстановка, ведущая вкладка сохранена, перезаписать файл, эхо в stdout

    tee /path/to/file <<EOF
    ${variable}
    EOF
    
  2. нет замены переменной, ведущая вкладка сохранена, перезаписать файл, эхо в stdout

    tee /path/to/file <<'EOF'
    ${variable}
    EOF
    
  3. переменной подстановки, вкладка ведущих удалены перезаписать файл, Эхо стандартный вывод

    tee /path/to/file <<-EOF
        ${variable}
    EOF
    
  4. переменная подстановка, ведущая вкладка сохранена,добавить файл, эхо в stdout

    tee -a /path/to/file <<EOF
    ${variable}
    EOF
    
  5. подстановка переменных, ведущая вкладка сохранена, перезаписать файл,нет эхо в stdout

    tee /path/to/file <<EOF >/dev/null
    ${variable}
    EOF
    
  6. вышеуказанное можно совместить с sudo а также

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

когда требуются права root

если для файла назначения требуются права root, используйте |sudo tee вместо >:

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

для будущих людей, у которых может быть эта проблема, работал следующий формат:

(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

в качестве экземпляра можно использовать:

первый (подключение 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

второй(выполнение команд):

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

третий(выполнение команд):

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

вперед (используя переменные):

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