过滤管道而不会丢失全部内容

时间:2013-01-02 11:30:29

标签: bash awk grep sh

标题可能含糊不清,但我有一个很好的例子:

echo "Test message:\nThis is a line.\nAnd this is another." | nail -s "`tail -1`" joe@localhost

这里的目标是将echo的内容作为消息正文发送,并使用最后一行作为主题。但是,当我这样做时,我会失去身体。

echo "Test message:\nThis is a line.\nAnd this is another." | nail joe@localhost

工作正常,但没有主题。

3 个答案:

答案 0 :(得分:2)

您可以使用命名管道来完成此操作:

mkfifo subj.fifo

echo "Test message:\nThis is a line.\nAnd this is another." |
  tee >(tail -n1 > subj.fifo) | mail -s "$(< subj.fifo)" joe@localhost

rm subj.fifo

请注意,如果您使用head而不是tail,则需要tee忽略SIGPIPE信号,例如trap '' PIPE

答案 1 :(得分:2)

由于您的主题出现在最后一行,您必须缓冲所有行(否则,无法确定哪一行是最后一行)。将主题放在第一行会容易得多。随你。这是一种可能的方法,使用bash 4.0中出现的mapfile

printf "%s\n" "Line one in the body of message" "Line two in the body of message" "Subject in the last line" | {
    mapfile -t array
    nail -s "${array[@]: -1}" joe@localhost < <(printf "%s\n" "${array[@]:0:${#array[@]}-1}")
}

如果您决定在第一行中想要主题,那么它就容易得多(当然,只是一个管道,没有多余的子壳或缓冲区):

printf "%s\n" "Subject in the first line" "Line one in the body of message" "Line two in the body of message"  | { read -r subject; nail -s "$subject" joe@localhost; }

答案 2 :(得分:1)

tail会丢弃最后一行之前的行。您可以使用临时文件,或将主题放在第一位而不是最后一位。无论哪种方式,管道都无法消耗和保持一条线,没有合作程序la tee

#!/bin/sh
# use first line as subject, args are recipients
# stdin is message body
read subj
( echo "$subj"; cat ) | nail -s "$subj" "$@"