我怎样才能写一个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 ))?
- 你想覆盖现有的文件,追加到现有的文件,或写入一个新的文件?
- 您的用户或其他用户(例如,
root
)是否拥有该文件? - 你想直接写heredoc的内容,还是让bash在你的heredoc中解释variables引用?
(还有其他的维度/子问题,我不认为重要的,考虑编辑这个答案来添加它们!)下面是上面列出的问题的维度的一些更重要的组合,各种不同的分隔标识符 – 没有什么神圣的EOF
,只要确保您用作分隔标识符的string不会在您的heredoc内发生:
-
要覆盖您拥有的现有文件(或写入新文件),请使用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
-
要追加一个你拥有的现有文件(或者写入一个新文件),用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
-
要覆盖您拥有的现有文件(或写入新文件),请使用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
-
要使用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
-
要覆盖由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
-
要追加由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的答案 ,这里有一些有用的组合。
-
variablesreplace,保留前导标签,覆盖文件,回显到标准输出
tee /path/to/file <<EOF ${variable} EOF
-
没有variablesreplace ,领先的选项卡保留,覆盖文件,回声到标准输出
tee /path/to/file <<'EOF' ${variable} EOF
-
variablesreplace, 引导标签删除 ,覆盖文件,回声到标准输出
tee /path/to/file <<-EOF ${variable} EOF
-
variablesreplace,保留前导标签, 追加到文件 ,回显到标准输出
tee -a /path/to/file <<EOF ${variable} EOF
-
variablesreplace,保留前导标签,覆盖文件, 没有回应到标准输出
tee /path/to/file <<EOF >/dev/null ${variable} EOF
-
以上可以和
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