无法缩进Heredoc以匹配嵌套的缩进


62

如果有一个“第一世界问题”来编写脚本,就是这样。

我要更新的脚本中包含以下代码:

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语句中,因此我似乎有两个选择:

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

我愿意使用Heredoc的替代方法,但是如果有解决方法,这是我的首选语法。

Answers:


113

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

#! /bin/bash
cat <<-EOF
    indented
    EOF
echo Done

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


不错,可以解决缩进问题$dateLastChanged,但是如果您在示例中使用hypen + quotes进行操作,但是如果我将连字符加引号并将EOI放在新行,它将再次开始扩展。
布莱奇利2013年

1
@JoelDavis:只需删除引号,并保留连字符。
choroba

5
被迫使用制表符非常烦人。有没有解决的办法?
con-f-use

2
@ con-f-use:您可以尝试类似方法cat << EOF | sed 's/^ *//'
choroba

4
甚至更好:cat <<- EOF | awk 'NR==1 && match($0, /^ +/){n=RLENGTH} {print substr($0, n+1)}'。这会从here文档中的每一行中删除第一行中的前一行空格(由于anubhava)。
con-f-use

5

如果您不需要在本文中进行命令替换和参数扩展,则可以通过在分隔符中添加前导空格来避免使用制表符:

$     cat << '    EOF'
>         indented
>     EOF
        indented
$     cat << '    EOF' | sed -r 's/^ {8}//'
>         unindented
>     EOF
unindented

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


1
对我来说,这是解决缩进问题而不使用空格的唯一答案。shell-check会发现与缩进的字符串中的空格不匹配的任何缩进更改。使用双引号进行参数扩展?
汤姆·黑尔

4

尝试这个:

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

在这种情况下,您不能在Heredoc中使用缩进的行。(这很重要,例如,如果内容是脚本。)
ivan_pozdeev

2

嗯...似乎您可以更好地利用--format此处的参数来--printf代替,而只是通过管道传递很多内容。另外,您if...fi是一个复合命令-它可以进行重定向,所有包含的命令都将继承该重定向,因此也许您根本不需要嵌套Heredoc。

if      [ "$diffLines" = 1 ]
then    stat --printf "Last Change: %.19y\n\n$(cat)\n" /.bbdata |
        mailx   -r  "Systems and Operations <sysadmin@[redacted].edu>" \
                -s  "Warning Stale BB Data" 'jadavis6@[redacted].edu'
else    echo    "$diffLines have changed"
fi      <<\STALE
This is an automated warning of stale data for the UNC-G Blackboard Snapshot process.
STALE

是的,我以前的修订版说我不介意sed/ awk部分。我今天进行的修订的一部分是将其删除,因为它与问题无关。无论哪种方式,都是六分之一。
布拉奇利

@Bratchley-该死 最后一句话将使我整日余下的时间分心。
mikeserv

你是什​​么意思?
布拉奇利

1
@Bratchley-看起来像个谜。
mikeserv

哈。不确定您来自哪个国家/地区,但这在美国很普遍。只是意味着“达到相同目的的不同方法”。您的解决方案确实绕过了Heredoc。
布拉奇利

0

另一个方法是herestrings:

    mail_content="Last Change: $dateLastChanged

    This is an automated warning of stale data for the UNC-G Blackboard Snapshot process."
    mailx -r "Systems and Operations <sysadmin@[redacted].edu>" -s "Warning Stale BB Data" jadavis6@[redacted].edu <<<"$mail_content"
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.