Bash 读取函数在使用换行符时返回错误代码

标签 bash io-redirection built-in

我有一个脚本,我从中返回多个值,每个值在一个新行上。为了将这些值捕获为 bash 变量,我使用了 read 内置函数(推荐 here )。

问题是,当我使用换行符作为read 的分隔符时,我似乎总是得到一个非零退出代码。这对检查操作结果的其余脚本造成了严重破坏。

这是我正在做的事情的精简版:

$ read -d '\n' a b c < <(echo -e "1\n2\n3"); echo $?; echo $a $b $c
1
1 2 3

注意 1 的退出状态。

我不想重写我的脚本(上面的 echo 命令)来使用不同的分隔符(因为在代码的其他地方使用新行是有意义的)。

如何让 read 在成功读取 3 个值时发挥良好并返回零退出状态?

更新

嗯,看来我可能错误地使用了“定界符”。从手册页:

-d *delim* 

  The first character of delim is used to terminate the input line,
  rather than newline.

因此,实现预期结果的一种方法是:

read -d '#' a b c < <(echo -e "1\n2\n3\n## END ##"); echo $?; echo $a $b $c

也许有更好的方法?

最佳答案

这里的“问题”是 read 在到达 EOF 时返回非零,当分隔符不在输入末尾时会发生这种情况。

因此,在您输入的末尾添加一个换行符将使其按您期望的方式工作(并将参数固定为 -d,如 gniourf_gniourf 的评论中所示)。

您的示例中发生的事情是 read 正在扫描 \ 并在找到它之前点击 EOF。然后输入行在 \n 上被拆分(因为 IFS)并分配给 $a, $b$c。然后 read 返回非零值。

为此使用 -d 很好,但是 \n 是默认分隔符,因此如果您这样做并且您有<,则不会更改任何内容/em> 得到了正确的分隔符 (-d $'\n') 首先你会看到你的例子根本不起作用(尽管它会返回 0 来自阅读)。 (参见 http://ideone.com/MWvgu7)

使用 read 时的一个常见习语(主要是 -d 的非标准值是测试 read 的返回值 < strong> 和 分配给的变量是否有值。read -d '' line || [ "$line"] 例如。即使在最后一个 "上读取失败时,它仍然有效line"的输入,因为末尾缺少终止符。

因此,为了让您的示例正常工作,您需要按照 chepner 指示的方式使用多个 read 调用,或者(如果您真的想要一个调用)然后您想要(参见 http://ideone.com/xTL8Yn):

IFS=$'\n' read -d '' a b c < <(printf '1 1\n2 2\n3 3')
echo $?
printf '[%s]\n' "$a" "$b" "$c"

并将 \0 添加到输入流的末尾(例如 printf '1 1\n2 2\n3 3\0')或将 | | [ "$a"] 最后将避免从 read 调用返回失败。

为读取设置 IFS 是为了防止 shell 对空格进行分词并错误地分解我的输入。 -d ''\0 上被读取

关于Bash 读取函数在使用换行符时返回错误代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33281837/

相关文章:

Bash——文件名中的 Rsync 变量有空格

linux - 了解 Unix 中的 I/O 重定向

javascript - innerWidth 和屏幕宽度显示相同的值?

perl - 获得所有Perl内置函数的列表的最佳方法是什么?

python - 有没有办法保护 python 中的内置函数?

linux - 在 ssh 中使用参数运行多个命令

bash - 如何从 lspci 中提取 pci 代码

bash - 强制排序命令忽略文件夹名称

linux - 无法访问 2>&1 : How to treat variable content as a redirection not as filename

.net - 如何避免进程终止通知和标准输出重定向事件之间的竞争条件?