【问题标题】:Why does read throw an error in bash but works fine?为什么 read 在 bash 中会抛出错误但工作正常?
【发布时间】:2018-07-26 06:27:32
【问题描述】:

此 bash 脚本将数组写入文件,然后将文件读回另一个数组。 (这对于脚本之间基于数组的通信很有用。)但是,IFS 行(第 12 行)捕获了一个奇怪的、未报告的错误。 为什么?

#!/bin/bash

# eso-error-ic

trap 'echo Error trapped, with code $?, on line ${LINENO}' ERR

# write data to a file
arr=(0 abc) && printf "%s\n" "${arr[@]}" > eso.out

# read data from the file into an array
# throws an error!!
IFS=$'\n' read -d '' -a new_arr < eso.out

# but it worked...
echo ${new_arr[0]}
echo ${new_arr[1]}

脚本输出:

Error trapped, with code 1, on line 12
0
abc

缺少的是在产生错误时显示的任何类型的消息。你得到的只是来自陷阱的消息,但没有关于什么错误的消息。

换句话说,IFS/read 行产生了一个错误,该错误被捕获,但没有显示错误消息,并且该行正确地将文件读入数组变量。它可以工作,不报告错误,但会捕获一个“错误”。

如果您注释掉陷阱行或切换到命令/eval/cat 方法将文件读入数组(如建议的here),则不会捕获错误。下面是这个脚本的 command/eval/cat 行的样子(替换第 12 行):

IFS=$'\n' GLOBIGNORE='*' command eval 'new_arr=($(cat eso.out))'

【问题讨论】:

  • 我可以在 MacOS High Sierra 上使用 Bash 3.2.57(1) 进行复制,只需 read -d '' variable &lt;&lt;&lt;"moo"; echo $?
  • 哇。更简单的回购!我已经在 CentOS 6/7、RHEL 6/7 上的 Bash 4 和 Apple Darwin 17.3 (High Sierra) 上的 Bash 3 和 4 上复制了它。
  • 跨站复制,详细说明:unix.stackexchange.com/questions/80045/…
  • 顺便说一下,set -e 和/或 ERR 陷阱通常被认为是一个坏主意。请参阅BashFAQ #105,如果赶时间,请跳过以下练习的寓言;或 set -e 的不同 shell 实现之间的不兼容性列表(以及相关的,其行为无法直观预测的程度)here
  • 顺便说一句,一般而言,我建议readarray -t new_arr &lt;eso.dat(如果您不需要与 bash pre-4.x 兼容)——除非您是从进程替换而不是文件读取,这样通过附加尾随或 NUL 来传递该进程的成功或失败到 read 的成功是一种非常有用的功能。

标签: linux bash shell unix ifs


【解决方案1】:

错误来自没有收到read 所期望的分隔符。我也一样

read -d x variable <<<"hello"

如果我将输入更改为"hellox",错误就会消失。

正如@Aserre 所提到的,详细的分析在我们的Unix & Linux sister site 中,正如@CharlesDuffy 所指出的,一个常见的解决方法是

read variable || [[ $variable ]]

即使没有-d 也可以使用它来处理可能缺少最终终止换行符的文件。

【讨论】:

  • 您可以从这个答案中消除不确定性。它是正确的,这就是为什么 read x || [[ $x ]] 在需要容忍缺少的分隔符时是一个习惯用法。
  • @tripleee 感谢您的解释。我仍然说在没有stderr-ing任何东西的情况下退出1是错误的。
猜你喜欢
  • 2021-06-25
  • 2011-08-04
  • 2014-09-15
  • 1970-01-01
  • 2012-04-06
  • 2021-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多