使用read命令读取成功但退出状态为1是否符合预期?
问题解答
一、退出状态为1是预期行为吗?
是的,这是bash中read命令的设计行为。当使用-d ''(指定空字符\0作为分隔符)时,read会持续读取直到遇到空字符,但<<<'hello'(here-string)提供的输入仅包含hello和换行符,没有空字符。因此read会读到输入结束(EOF),此时返回退出状态1,表示未找到指定分隔符,但它已经将读到的所有内容(hello)存入了目标变量。
二、用!反转退出码可行吗?
可以,但并非最严谨的方案。在该行开头添加!确实会将退出状态1反转成0,让启用set -e的脚本不会中断,但如果read真的发生了其他错误(比如无法读取输入),反转后也会返回0,掩盖真实问题。
三、更合适的解决方法
针对你读取多行JSON内容的场景,推荐两种更稳妥的方式:
1. 保留read并显式处理退出码
可以判断read的退出码,仅当它是因未找到分隔符(而非其他错误)时手动返回成功:
IFS='' read -r -d '' SLACK_PAYLOAD <<'JSON' { "channel": $channel, "blocks": [ { "type": "section", "text": { "type": "mrkdwn", "text": $message } }, { "type": "section", "text": { "type": "mrkdwn", "text": $changelog } } ] } JSON # 若read因未找到分隔符返回1,手动将状态置为成功 [[ $? -eq 1 ]] && true
2. 改用cat结合命令替换(更简洁)
如果不需要read的特殊特性,用命令替换读取here-doc更直观,退出码自然为0:
SLACK_PAYLOAD=$(cat <<'JSON' { "channel": $channel, "blocks": [ { "type": "section", "text": { "type": "mrkdwn", "text": $message } }, { "type": "section", "text": { "type": "mrkdwn", "text": $changelog } } ] } JSON )
注意:
<<'JSON'会阻止变量展开,若需要$channel、$message等变量被替换,需去掉单引号,写成<<JSON。
补充说明
你的脚本启用了set -eio pipefail,其中set -e会让脚本在命令返回非0状态时直接退出,因此read返回1会导致脚本中断。上述两种方法都能避免这个问题,第二种方法更适合多行文本赋值的场景。
内容的提问来源于stack exchange,提问作者mpen
相关产品推荐
相关产品推荐

