web-dev-qa-db-ja.com

Bashスクリプトでファイルにヒアドキュメントを書き込む方法はありますか。

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

643
Joshua Enfield

Advanced Bash-Scripting Guideを読んでください 第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)は、Wordの前に空白があってはいけません。これは、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

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

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

catとI/Oリダイレクションを使用する代わりに、代わりにteeを使用すると便利です。

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

それはより簡潔です、そしてあなたがルートパーミッションでファイルに書く必要があるならそれはSudoと結合されることができるリダイレクト演算子とは違ってプラス。

124
Livven

注:

質問(bashスクリプトでヒアドキュメント(別名heredoc)をファイルに書き込む方法)には、(少なくとも)3つの独立したディメンションまたはサブクエストがあります。

  1. 既存のファイルを上書きしますか、既存のファイルに追加しますか、それとも新しいファイルに書き込みますか?
  2. あなたのユーザまたは他のユーザ(例えばroot)がファイルを所有していますか?
  3. あなたのヒアドキュメントの内容を文字通りに書いてみたいですか?

(私は重要ではないと思う他のディメンション/サブクエストがあります。それらを追加するためにこの答えを編集することを検討してください!) EOFについては神聖です。あなたの区切り識別子として使う文字列がnotがあなたの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
    
49
TomRoche

@ Livvenの answer の上に構築するために、ここにいくつかの便利な組み合わせがあります。

  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
    
28
go2null

Root権限が必要な場合

宛先ファイルにroot権限が必要な場合は、|Sudo teeではなく>を使用してください。

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

この問題を抱えているかもしれない将来の人々のために以下のフォーマットはうまくいきました:

(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

例としてあなたはそれを使用することができます:

まず(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

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
2
MLSC

私はインデントされたスクリプトで簡潔さ、読みやすさと提示のためにこのメソッドが好きです:

<<-End_of_file >file
→       foo bar
End_of_file

→       は tab キャラクター。

0
daniel Azuelos