我如何在这里写一个文档到Bash脚本文件?


当前回答

注意:

以下是本主题中其他答案的浓缩和组织,尤其是Stefan Lasiewski和Serge Stroobandt的优秀作品 Lasiewski和我推荐高级bash脚本编写指南中的Ch 19 (Here Documents)

问题(如何在bash脚本中将here文档(又名heredoc)写入文件?)有(至少)3个主要的独立维度或子问题:

要覆盖现有文件、追加到现有文件还是写入新文件? 您的用户或其他用户(例如root)拥有该文件吗? 您是想按字面意思写heredoc的内容,还是让bash在heredoc内解释变量引用?

(还有其他我认为不重要的方面/子问题。考虑编辑这个答案来添加它们!)下面是上面列出的问题的一些更重要的维度组合,使用各种不同的分隔标识符——关于EOF没有什么神圣的,只要确保你用作分隔标识符的字符串没有出现在你的heredoc中:

To overwrite an existing file (or write to a new file) that you own, substituting variable references inside the 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 To append an existing file (or write to a new file) that you own, substituting variable references inside the 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 To overwrite an existing file (or write to a new file) that you own, with the literal contents of the 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 To append an existing file (or write to a new file) that you own, with the literal contents of the 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 To overwrite an existing file (or write to a new file) owned by root, substituting variable references inside the 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 To append an existing file (or write to a new file) owned by user=foo, with the literal contents of the 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

其他回答

例如,你可以使用它:

首先(进行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

第二个(executing的聚会):

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

此外,如果您正在写入一个文件,检查写入是否成功或失败可能是一个好主意。例如:

if ! echo "contents" > ./file ; then
    echo "ERROR: failed to write to file" >& 2
    exit 1
fi

要对heredoc进行同样的操作,有两种可能的方法。

1)

if ! cat > ./file << EOF
contents
EOF
then
    echo "ERROR: failed to write to file" >& 2
    exit 1
fi

if ! cat > ./file ; then
    echo "ERROR: failed to write to file" >& 2
    exit 1
fi << EOF
contents
EOF

您可以通过将目标文件./file替换为/file(假设您不是以根用户身份运行)来测试上述代码中的错误情况。

当需要root权限时

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

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

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

如果你想保持heredoc的缩进可读性:

$ perl -pe 's/^\s*//' << EOF
     line 1
     line 2
EOF

Bash中支持缩进式heredoc的内置方法只支持开头制表符,不支持空格。

Perl可以用awk代替,以节省几个字符,但是如果您知道基本的正则表达式,Perl可能更容易记住。

对于将来可能遇到这个问题的人,下面的格式是有效的:

(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