如果说脚本编写存在“第一世界问题”,那么就是这个了。
我正在更新的脚本中有以下代码:
if [ $diffLines -eq 1 ]; then
dateLastChanged=$(stat --format '%y' /.bbdata | awk '{print $1" "$2}' | sed 's/\.[0-9]*//g')
mailx -r "Systems and Operations <sysadmin@[redacted].edu>" -s "Warning Stale BB Data" jadavis6@[redacted].edu <<EOI
Last Change: $dateLastChanged
This is an automated warning of stale data for the UNC-G Blackboard Snapshot process.
EOI
else
echo "$diffLines have changed"
fi
该脚本发送电子邮件没有问题,但 mailx 命令嵌套在 if 语句中,因此我似乎有两个选择:
- 换
EOI
一个新行并打破缩进模式或 - 保持缩进,但使用 echo 语句之类的东西让 mailx 吸收我的电子邮件。
我对heredoc的替代方案持开放态度,但如果有办法解决这个问题,它是我的首选语法。
答案1
您可以将here-doc运算符更改为<<-
。然后您可以缩进此处文档和分隔符带选项卡:
#! /bin/bash
cat <<-EOF
indented
EOF
echo Done
注意你必须使用标签,而不是空格,来缩进此处文档和分隔符。这意味着上面的示例将无法复制(Stack Exchange 用空格替换制表符)。如果在第一个分隔符周围添加任何引号EOF
,则参数扩展、命令替换和算术扩展将不会生效。
答案2
如果您不需要在此处文档中进行命令替换和参数扩展,则可以通过在分隔符中添加前导空格来避免使用制表符:
$ cat << ' EOF'
> indented
> EOF
indented
$ cat << ' EOF' | sed -r 's/^ {8}//'
> unindented
> EOF
unindented
不过,我无法找到使用此技巧并保持参数扩展的方法。
答案3
尝试这个:
sed 's/^ *//' >> ~/Desktop/text.txt << EOF
Load time-out reached and nothing to resume.
$(date +%T) - Transmission-daemon exiting.
EOF
答案4
这个答案是 GNU-Bash 特定的。
诀窍是我们使用<<<
Bash 提供的单字here-doc,并将其设为多行项目。
我们还避免了 UUoC:我们不需要一个cat
流程来将输入提供给sed
:
$ sed '1d;s/^ //' <<<"
{
TERM=$TERM
}
bye"
输出显示前导四空格缩进已删除并$TERM
扩展:
{
TERM=xterm-256color
}
bye
1d
中的命令是sed
删除第一个空行,该空行之所以存在,是因为我们的引用文字在开始引号后以换行符开头。
当然,在真实的脚本中,这是凹痕ed——请原谅我,在照顾ed——我们将大括号与命令对齐sed
,该命令将在循环或条件内缩进。
如果我们以分隔符开始数据的每一行,那么简单的sed
替换将删除可变数量的缩进,以便块可以在缩进级别之间自由移动:
while command ; do
if condition ; then
variable=$(sed '1d;s/^.*|//' <<<"
|{
| TERM=$TERM
|}
|bye
")
fi
done
最后一个想法是将缩进魔法放入一个用作某种宏的变量中:
# put in some common definitions library section
indent='sed 1d;s/^.*|//'
# ...
while command ; do
if condition ; then
variable=$($indent <<<"
|{
| TERM=$TERM
|}
|bye
")
fi
done
我们可以通过编写一个好的老式函数来改进这一点:
# put in some common definitions library section
ind()
{
sed '1d;s/^.*|//' <<<$1
}
# ...
while command ; do
if condition ; then
variable=$(ind "
|{
| TERM=$TERM
|}
|bye
")
fi
done
然后我们就完全抽象出来了<<<
。