我正在编写一个巨大的脚本工厂脚本,为我的服务器生成大量维护脚本。
直到现在我写了一些需要写在一行中的行,echo -ne例如
echo -n "if (( " | sudo tee -a /usr/local/bin/upgradeAllServers &> /dev/null
# Generate exitCode check for each Server
IFS=" "
COUNT=0
while read -r name ipAddr
do
if(($COUNT != 0))
then
echo -n " || " | sudo tee -a /usr/local/bin/upgradeAllServers &> /dev/null
fi
echo -n "(\$"$name"_E != 0 && \$"$name"_E != 1)" | sudo tee -a /usr/local/bin/upgradeAllServers &> /dev/null
COUNT=$((COUNT+1))
JOBSDONE=$((JOBSDONE+1))
updateProgress $JOBCOUNT $JOBSDONE
done <<< "$(sudo cat /root/.virtualMachines)"
echo " ))" | sudo tee -a /usr/local/bin/upgradeAllServers &> /dev/null
Run Code Online (Sandbox Code Playgroud)
这会生成我(如果我的配置文件中有例如 2 个服务器)代码如下
if (( ($server1_E != 0 && $server1_E != 1) || ($server2_E != 0 && $server2_E != 1) ))
Run Code Online (Sandbox Code Playgroud)
所有其他不需要这种内联编写代码的代码块我使用 heredocs 生成,因为我发现它们的编写和维护方式更好。例如,在上层代码之后,我生成了其余的代码
cat << EOF | sudo tee -a /usr/local/bin/upgradeAllServers &> /dev/null
then
# Print out ExitCode legend
echo " ExitCode 42 - upgrade failed"
echo " ExitCode 43 - Upgrade failed"
echo " ExitCode 44 - Dist-Upgrade failed"
echo " ExitCode 45 - Autoremove failed"
echo ""
echo ""
fi
EOF
Run Code Online (Sandbox Code Playgroud)
所以最终的代码块看起来像
if (( ($server1_E != 0 && $server1_E != 1) || ($server2_E != 0 && $server2_E != 1) ))
then
# Print out ExitCode legend
echo " ExitCode 42 - upgrade failed"
echo " ExitCode 43 - Upgrade failed"
echo " ExitCode 44 - Dist-Upgrade failed"
echo " ExitCode 45 - Autoremove failed"
echo ""
echo ""
fi
Run Code Online (Sandbox Code Playgroud)
我的问题
有没有办法让heredoc 的行为类似于echo -ne没有行尾符号的情况?
cho*_*oba 10
不,heredoc 总是以换行符结尾。但是您仍然可以删除最后一个换行符,例如使用 Perl:
cat << 'EOF' | perl -pe 'chomp if eof'
First line
Second line
EOF
Run Code Online (Sandbox Code Playgroud)
有没有办法让heredoc的行为类似于没有行尾符号的echo -ne?
简短的回答是,heredoc 和 herestrings 只是以这种方式构建的,所以不 - here-doc 和 herestring 将始终添加一个尾随换行符,并且没有选项或本机方法可以禁用它(也许在未来的 bash 版本中会有?)。
但是,通过仅使用 bash 的方式来处理它的一种方法是通过标准while IFS= read -r方法读取 heredoc 给出的内容,但添加延迟并通过printf不带尾随换行符的方式打印最后一行。以下是仅使用 bash 可以做的事情:
#!/usr/bin/env bash
while true
do
IFS= read -r line || { printf "%s" "$delayed";break;}
if [ -n "$delayed" ];
then
printf "%s\n" "$delayed"
fi
delayed=$line
done <<EOF
one
two
EOF
Run Code Online (Sandbox Code Playgroud)
你在这里看到的是通常的 while 循环IFS= read -r line方法,但是每一行都存储到一个变量中,因此延迟了(所以我们跳过打印第一行,存储它,只有当我们阅读第二行时才开始打印)。这样我们就可以捕获最后一行,当下一次迭代read返回退出状态 1 时,那是我们通过printf. 冗长?是的。但它有效:
$ ./strip_heredoc_newline.sh
one
two$
Run Code Online (Sandbox Code Playgroud)
注意$提示字符被向前推,因为没有换行符。作为奖励,这个解决方案是便携和POSIX十岁上下,所以它应该在工作ksh和dash为好。
$ dash ./strip_heredoc_newline.sh
one
two$
Run Code Online (Sandbox Code Playgroud)
我建议您尝试不同的方法。而不是从多个 echo 语句和 heredocs 中拼凑生成的脚本。我建议您尝试使用单个 heredoc。
您可以在 heredoc 中使用变量扩展和命令替换。就像在这个例子中:
#!/bin/bash
cat <<EOF
$USER $(uname)
EOF
Run Code Online (Sandbox Code Playgroud)
我发现这通常会导致比逐个生成输出更具可读性的最终结果。
此外,您似乎忘记了#!脚本开头的那一行。该#!行在任何格式正确的脚本中都是强制性的。尝试运行没有该#!行的脚本只会在您从处理格式错误的脚本的 shell 中调用它时才有效,即使在这种情况下,它最终可能会被与您预期不同的 shell 解释。
Heredocs 总是以换行符结尾,但您可以简单地将其删除。我知道的最简单的方法是使用head程序:
head -c -1 <<EOF | sudo tee file > /dev/null
my
heredoc
content
EOF
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8476 次 |
| 最近记录: |