无法缩进 heredoc 以匹配代码块的缩进

Bra*_*ley 92 shell bash shell-script here-document

如果脚本编写存在“第一世界问题”,那就是它。

我正在更新的脚本中有以下代码:

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
Run Code Online (Sandbox Code Playgroud)

该脚本发送电子邮件没有问题,但 mailx 命令嵌套在 if 语句中,因此我似乎有两个选择:

  1. EOI一个新的生产线,打破花纹或
  2. 保持缩进,但使用类似 echo 语句的东西让 mailx 接收我的电子邮件。

我对heredoc的替代品持开放态度,但如果有办法解决这个问题,这是我的首选语法。

cho*_*oba 154

您可以将 here-doc 运算符更改为<<-. 然后,您可以使用制表缩进 here-doc和分隔符:

#! /bin/bash
cat <<-EOF
    indented
    EOF
echo Done
Run Code Online (Sandbox Code Playgroud)

请注意,您必须使用 tabs而不是空格来缩进 here-doc。这意味着上面的示例将无法复制(Stack Exchange 用空格替换制表符)。第一个EOF分隔符周围不能有任何引号,否则参数扩展、命令替换和算术扩展无效。

  • 被迫使用标签是非常烦人的。有什么好的解决方法吗? (11认同)
  • 或者甚至更好:`cat &lt;&lt;- EOF | awk 'NR==1 &amp;&amp; match($0, /^ +/){n=RLENGTH} {print substr($0, n+1)}'`。这将从此处文档中的每一行中删除第一行中的前面空格量(感谢 [anubhava](http://stackoverflow.com/a/33837099/789308))。 (6认同)
  • 实际上,唯一需要 &lt;Tab&gt; 的行是最后的“EOF”行。其余行可以使用空格。(至少在 Bash v4 中......之前不确定。) (3认同)
  • @JoelDavis:只需删除引号,保留连字符。 (2认同)
  • @con-f-use:你可以尝试类似`cat &lt;&lt; EOF | sed 's/^ *//'` 等等。 (2认同)

its*_*dok 15

如果您的 here-document 中不需要命令替换和参数扩展,则可以通过将前导空格添加到分隔符来避免使用制表符:

$     cat << '    EOF'
>         indented
>     EOF
        indented
$     cat << '    EOF' | sed -r 's/^ {8}//'
>         unindented
>     EOF
unindented
Run Code Online (Sandbox Code Playgroud)

不过,我想不出使用这个技巧并保持参数扩展的方法。

  • 对我来说,这是不使用空格解决缩进问题的唯一答案。`shell-check` 将查找任何与引用字符串中的空格不匹配的缩进更改。使用双引号进行参数扩展? (2认同)
  • 好的。您可以通过 envsubst 进行管道传输,将环境变量替换为其值。 (2认同)

小智 5

尝试这个:

sed 's/^ *//' >> ~/Desktop/text.txt << EOF
    Load time-out reached and nothing to resume.
    $(date +%T) - Transmission-daemon exiting.
EOF
Run Code Online (Sandbox Code Playgroud)