我怎样才能写一个heredoc Bash脚本中的文件?

如何在Bash脚本中将文档写入文件?

阅读高级Bash脚本指南第19章这里的文档 。

这是一个将内容写入/tmp/yourfilehere这个文件的例子

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

请注意,最后的'EOF'(The LimitString )在单词的前面不应该有任何空格,因为这意味着LimitString不会被识别。

在shell脚本中,您可能希望使用缩进来使代码可读,但是这可能会导致在您的文档中缩进文本的不良效果。 在这种情况下,使用<<- (后面跟一个破折号)来禁用前导制表符( 注意 ,为了testing这个,你需要用一个制表符replace前面的空白符号 ,因为我不能在这里打印实际制表符)。

 #!/usr/bin/env bash if true ; then cat <<- EOF > /tmp/yourfilehere The leading tab is ignored. EOF fi 

如果您不想在文本中解释variables,请使用单引号:

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

通过命令pipe道来pipe理heredoc:

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

输出:

 foo bbr bbz 

…或者使用sudo将heredoc写入文件:

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

而不是使用cat和I / Oredirect,而是使用tee来代替:

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

它更简洁,而且与redirect操作符不同,如果需要使用根权限写入文件,则可以将它与sudo结合使用。

注意:

  • 以下内容浓缩并组织其他答案,特别是Stefan Lasiewski和Serge Stroobandt的出色工作
  • Lasiewski和我推荐高级Bash脚本指南中的Ch 19(Here Documents)

(至less)3个主要的独立维度或子问题(如何在bash脚本中写入一个here文件(aka heredoc ))?

  1. 你想覆盖现有的文件,追加到现有的文件,或写入一个新的文件?
  2. 您的用户或其他用户(例如, root )是否拥有该文件?
  3. 你想直接写heredoc的内容,还是让bash在你的heredoc中解释variables引用?

(还有其他的维度/子问题,我不认为重要的,考虑编辑这个答案来添加它们!)下面是上面列出的问题的维度的一些更重要的组合,各种不同的分隔标识符 – 没有什么神圣的EOF ,只要确保您用作分隔标识符的string不会在您的heredoc内发生:

  1. 要覆盖您拥有的现有文件(或写入新文件),请使用heredoc中的variables引用:

     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中的variables引用代替:

     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内部replacevariables引用:

     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 

要build立在@ Livven的答案 ,这里有一些有用的组合。

  1. variablesreplace,保留前导标签,覆盖文件,回显到标准输出

     tee /path/to/file <<EOF ${variable} EOF 
  2. 没有variablesreplace ,领先的选项卡保留,覆盖文件,回声到标准输出

     tee /path/to/file <<'EOF' ${variable} EOF 
  3. variablesreplace, 引导标签删除 ,覆盖文件,回声到标准输出

     tee /path/to/file <<-EOF ${variable} EOF 
  4. variablesreplace,保留前导标签, 追加到文件 ,回显到标准输出

     tee -a /path/to/file <<EOF ${variable} EOF 
  5. variablesreplace,保留前导标签,覆盖文件, 没有回应到标准输出

     tee /path/to/file <<EOF >/dev/null ${variable} EOF 
  6. 以上可以和sudo结合使用

     sudo -u USER tee /path/to/file <<EOF ${variable} 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 

何时需要root权限

当目标文件需要root权限时,使用|sudo tee而不是>

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

作为例子,你可以使用它:

首先(使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 

第四(使用variables):

 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