Как я могу записать heredoc в файл скриптом Bash? - PullRequest
658 голосов
/ 02 июня 2010

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

Ответы [ 8 ]

924 голосов
/ 02 июня 2010

Прочтите Руководство по расширенному написанию сценариев Глава 19. Здесь документы .

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

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

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

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

#!/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
128 голосов
/ 13 июня 2013

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

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

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

51 голосов
/ 18 сентября 2014

Примечание:

Вопрос (как записать здесь документ (он же 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
    
31 голосов
/ 03 августа 2016

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

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

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

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

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

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

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

    sudo -u USER tee /path/to/file <<EOF
    ${variable}
    EOF
    
15 голосов
/ 14 февраля 2014

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

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

cat << 'EOF' |sudo tee /tmp/yourprotectedfilehere
The variable $FOO will *not* be interpreted.
EOF
11 голосов
/ 02 июня 2010

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

(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
2 голосов
/ 16 февраля 2014

Например, вы можете использовать его:

Первый (соединение 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

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

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
0 голосов
/ 15 ноября 2018

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

<<-End_of_file >file
→       foo bar
End_of_file

Где - это символ .

...