我有一个脚本,我从中返回多个值,每个值在一个新行上。为了将这些值捕获为 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/