ヒアドキュメントをBashスクリプトのファイルに書き込むにはどうすればよいですか?


回答:


1073

Advanced Bash-Scripting Guide Chapter 19. Here Documentsをお読みください。

内容をファイルに書き込む例を次に示します /tmp/yourfilehere

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

最後の 'EOF'(The 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

ヒアドキュメントをコマンドパイプライン経由でパイプするには:

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

出力:

foo
bbr
bbz

...または、以下を使用して、ヒアドキュメントをファイルに書き込みますsudo

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

11
Bashは必要ありません。この機能はBourne / Korn / POSIXシェルにもあります。
Janus Troelsen、2013年

5
何を<<<、彼らは何と呼ばれていますか?
ユルゲンポール

18
@PineappleUndertheSea <<<は「ヒア文字列」と呼ばれます。のようなコードtr a-z A-Z <<< 'one two three'は文字列になりますONE TWO THREE。詳細については、en.wikipedia.org
wiki / Here_document#Here_strings

8
最後のEOFのに空白があってはなりません。少なくともbashでは、これにより区切り文字として認識されなくなります
carpii

10
この特定のヒアドキュメントは、置換を含むのではなく、文字通りの内容を意図しているため、ではなくにする必要が<<'EOF'あり<<EOFます。
Charles Duffy

152

代わりに使用するcatと、I / Oリダイレクション使用すると便利かもしれませんtee代わりに:

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

これはより簡潔です。また、リダイレクトオペレーターとは異なり、sudoroot権限でファイルに書き込む必要がある場合に組み合わせることができます。


18
> /dev/nullhereファイルの内容が作成時にstdoutに表示されないように、最初の行の末尾に追加することをお勧めします。
Joe Carroll

11
確かに、しかしあなたの解決策sudoはその簡潔さのためではなく、との互換性のために私にアピールしました:-)
Joe Carroll

2
この方法を使用して、既存のファイルにどのように追加しますか?
MountainX

5
@MountainXチェックアウトman tee-a上書きする代わりにフラグを使用して追加します。
Livven 2013

3
私が時々監視する必要がある設定スクリプトで使用するために、内容を出力するので、これがさらに好きです。
Alois Mahdal 2013

59

注意:

質問(hereドキュメント(別名heredoc)をbashスクリプトのファイルに書き込む方法は?)には、(少なくとも)3つの主要な独立した次元またはサブ質問があります。

  1. 既存のファイルを上書きするか、既存のファイルに追加するか、または新しいファイルに書き込みますか?
  2. あなたのユーザーまたは別のユーザー(例root:)がファイルを所有していますか?
  3. ヒアドキュメントの内容を文字どおりに記述しますか、それともヒアドキュメント内の変数参照をbashに解釈させますか?

(私が重要とは思わない他の次元/サブ質問があります。それらを追加するには、この回答を編集することを検討してください!)ここに、さまざまな区切り識別子を使用して、上記の質問の次元のより重要な組み合わせのいくつかを示します-何もありません神聖なEOF、あなたの区切り識別子として使用する文字列があなたのヒアドキュメント内に出現しないことを確認してください:

  1. 所有している既存のファイルを上書きする(または新しいファイルに書き込む)には、ヒアドキュメント内の変数参照を置き換えます。

    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. 所有している既存のファイルを追加する(または新しいファイルに書き込む)には、ヒアドキュメント内の変数参照を置き換えます。

    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. ヒアドキュメントのリテラル内容で、所有している既存のファイルを上書きする(または新しいファイルに書き込む)には:

    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. ヒアドキュメントのリテラル内容を使用して、所有している既存のファイルを追加する(または新しいファイルに書き込む)には:

    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. ルートが所有する既存のファイルを上書きする(または新しいファイルに書き込む)には、ヒアドキュメント内の変数参照を置き換えます。

    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が所有する既存のファイルを追加する(または新しいファイルに書き込む)には:

    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
    

#6が最適です。しかし、既存のファイルの内容を#6でどのように上書きしますか?
Aleksandr Makov

2
@Aleksandr Makov:既存のファイルの内容を#6でどのように上書きしますか?-a==を省略し--appendます。つまり、tee -a-> teeです。参照してくださいinfo tee。(私はそれをここに引用したいが、コメントのマークアップがあまりにも限られている
TomRoche

1
代わりに猫とTシャツにパイピングを使用する#6に利点はありsudo tee /path/to/your/file << 'Screw_you_Foo'ますか?
codemonkee 2017年

なぜ追加の例のFOE代わりにEOF
becko

2
@becko:ラベルが単なるラベルであることを示すため。各例で異なるラベルを使用したことに注意してください。
TomRoche 2018

41

@Livvenの答えに基づいて、いくつかの便利な組み合わせを示します。

  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

16

ルート権限が必要な場合

宛先ファイルにroot権限が必要な場合は、|sudo tee代わりにを使用して>ください:

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

ヒアドキュメントに変数を渡すことは可能ですか?$ FOOが解釈されるようにするにはどうすればよいでしょうか?
user1527227 14

@ user1527227ここでの例のファイルのように:変数$ FOOは解釈されません。
Serge Stroobandt 2014

以下では、この回答をStefan Lasiewskiの回答と組み合わせて整理することを試みました。
TomRoche

3
@ user1527227 EOFを一重引用符で囲まないでください。次に$ FOOが解釈されます。
imnd_neel 2017

11

この問題が発生する可能性のある将来の人々のために、次のフォーマットが機能しました:

(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

6
括弧は必要ありませんcat << END > afile。ヒアドキュメントが続くと、完全にうまく機能します。
グレンジャックマン

おかげで、これは実際に私が遭遇した別の問題を解決しました。ここのいくつかのドキュメントの後にいくつかの問題がありました。上記のアドバイスのように、それはそれを修正したので、それは括弧と関係があったと思います。
Joshua Enfield

2
これは機能しません。cat受け入れられた回答に示されているように、出力リダイレクトは、行の終わりで始まる必要があります。
追って通知があるまで一時停止。

2
@DennisWilliamsonそれが機能する、それが括弧が何のためにあるのかです。全体catがサブシェルの内部で実行され、サブシェルのすべての出力はファイルにリダイレクトされます
Izkata

2
@Izkata:この回答の編集履歴を見ると、コメントをする前に括弧が削除され、後で追加されました。グレン・ジャックマンの(そして私の)コメントが適用されます。
追って通知があるまで一時停止。

3

インスタンスとしてそれを使用できます:

最初(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

2番目(コマンドを実行):

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

3番目(コマンドを実行):

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

-1

インデントされたスクリプトでの簡潔さ、読みやすさ、およびプレゼンテーションのために、この方法が好きです。

<<-End_of_file >file
       foo bar
End_of_file

キャラクター→       はどこですかtab

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.