Answers:
阅读《高级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脚本中,您可能希望使用缩进来使代码可读,但是,这会对在here文档中缩进文本产生不良影响。在这种情况下,请使用<<-
(后接破折号)禁用前导制表符(请注意,要进行测试,您需要将前导空格替换为一个制表符,因为我无法在此处打印实际的制表符。)
#!/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
以下方法将Heredoc写入文件:
cat <<'EOF' | sed 's/a/b/' | sudo tee /etc/config_file.conf
foo
bar
baz
EOF
<<<
又叫什么呢?
<<<
被称为“这里字符串”。像这样的代码tr a-z A-Z <<< 'one two three'
将导致字符串ONE TWO THREE
。有关详细信息,请访问en.wikipedia.org/wiki/Here_document#Here_strings
<<'EOF'
而不是<<EOF
。
除了使用cat
I / O重定向之外,还可以使用以下方法tee
:
tee newfile <<EOF
line 1
line 2
line 3
EOF
它更加简洁,而且与重定向运算符不同,sudo
如果您需要写入具有root权限的文件,可以将其与结合使用。
> /dev/null
在第一行的末尾添加,以防止在创建文件时将here文件的内容显示到stdout。
sudo
,而不是因为它的简洁:-)
man tee
。使用该-a
标志附加而不是覆盖。
注意:
问题(如何在bash脚本中将here文档(aka Heredoc)写入文件?)具有(至少)3个主要的独立维度或子问题:
root
)是否拥有该文件?(还有其他我认为不重要的维度/子问题。请考虑编辑此答案以添加它们!)以下是上述问题的维度的一些更重要的组合,带有各种不同的定界标识符-没有任何内容神圣EOF
,只需确保您用作定界标识符的字符串不会出现在Heredoc中:
要覆盖您拥有的现有文件(或写入新文件),请在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
要附加您拥有的现有文件(或写入新文件),请在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
要使用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中替换变量引用:
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
要附加用户= 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
-a
== --append
; 即tee -a
-> tee
。请参阅info tee
(我在这里引用了它,但是评论标记太有限了
sudo tee /path/to/your/file << 'Screw_you_Foo'
吗?
FOE
而不是EOF
在附加示例中?
要以@Livven的答案为基础,以下是一些有用的组合。
变量替换,保留前导选项卡,覆盖文件,回显到stdout
tee /path/to/file <<EOF
${variable}
EOF
无变量替换,保留前导选项卡,覆盖文件,回显到stdout
tee /path/to/file <<'EOF'
${variable}
EOF
变量替换,删除前导选项卡,覆盖文件,回显到stdout
tee /path/to/file <<-EOF
${variable}
EOF
变量替换,保留前导选项卡,追加到文件,回显到stdout
tee -a /path/to/file <<EOF
${variable}
EOF
变量替换,保留前导选项卡,覆盖文件,不回显stdout
tee /path/to/file <<EOF >/dev/null
${variable}
EOF
以上可以结合sudo
以及
sudo -u USER tee /path/to/file <<EOF
${variable}
EOF
如果目标文件需要root权限,请使用|sudo tee
代替>
:
cat << 'EOF' |sudo tee /tmp/yourprotectedfilehere
The variable $FOO will *not* be interpreted.
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
cat << END > afile
紧随其后的Heredoc效果很好。
cat
在以接受的答案所示的开头的行的末尾。
cat
在一个子外壳中运行,并且该子外壳的所有输出都重定向到文件
例如,您可以使用它:
首先(建立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
第四(使用变量):
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