Shell脚本中从标准输入管道取得数据

需求

前两年写过一个webhook《Telegram机器人开发初步——一个Grafana告警机器人》,但是那个只能传入简单的字符串组成的JSON参数。

这回的问题是,我需要把一个脚本执行的结果——通过标准输出的大段日志内容通过这个webhook发送给tg机器人。常规的方法是这样:

source.sh | send_to_tgbot.sh

其中的send_to_tgbot.sh是类似这样的:

curl -XPOST -d "{\"message\": \"$1\"}" https://yourdomain/tgbot_xxx

这样显然是无法实现所需要的功能的。

解决

首先是要读取通过管道进来的标准输入的内容到参数中,最简单的方法就是把它cat到变量里:

MSG=$(cat)
curl -XPOST -d "{\"message\": \"$MSG\"}" https://yourdomain/tgbot_xxx

但是这样直接把这个变量放到JSON里会有问题,因为其中会有很多控制字符会破坏JSON的结构,需要转义一下:

MSG=$(printf "%q" "$(cat)")

但这样转义以后就会给结果字符串加上:$'',还得用sed去掉一下,顺便再给双引号也加上转义:

MSG=$(printf "%q" "$(cat)"  | sed 's/^$'\''//; s/'\''$//; s/\"/\\"/g')

最后给参数加上选项-,指定使用标准输入,否则仍然按原来传参方式使用:

MSG=$1
if [ "$MSG" = "-" ]
then
        MSG=$(printf "%q" "$(cat)"  | sed 's/^$'\''//; s/'\''$//; s/\"/\\"/g')
fi

推送到[go4pro.org]