Как написать heredoc в файл в Bash script?

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

Ответ 1

Прочтите расширенный Bash -Scripting Guide Глава 19. Здесь Документы.

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

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

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

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

#!/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

Ответ 2

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

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

Это более краткий, плюс в отличие от оператора перенаправления его можно комбинировать с sudo, если вам нужно писать в файлы с правами root.

Ответ 3

Замечания:

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

Ответ 4

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

  • подстановка переменных, ведущая вкладка сохранена, перезаписывает файл, echo to stdout

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

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

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

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

    tee /path/to/file <<EOF >/dev/null
    ${variable}
    EOF
    
  • приведенное выше можно объединить с sudo, а также

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

Ответ 5

Если требуются права root

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

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

Ответ 6

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

(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

Ответ 7

В качестве примера вы можете использовать его:

Сначала (создание ssh-соединения):

while read pass port user ip files directs; do
    sshpass -p$pass scp -o 'StrictHostKeyChecking no' -P $port $files [email protected]$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 [email protected]$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 [email protected]$ip "$Script"

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

Forth (с использованием переменных):

while read pass port user ip fileoutput; do
    sshpass -p$pass ssh -o 'StrictHostKeyChecking no' -p $port [email protected]$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

Ответ 8

Мне нравится этот метод для получения четкости, удобочитаемости и представления в отступом:

<<-End_of_file >file
→       foo bar
End_of_file

Где - символ tab.