我有file
三行:
1
2
3
当先做read a < file
,再做echo $a
,结果总是一样的,即1
。
我想read
从上次中断的地方继续。我该怎么做?如果不可能,那么read
在 中使用时它是如何工作的while read; do some_stuff; done < file
?
答案1
每次read a < file
打开一次file
并从头开始阅读。另一方面,while read; do some_stuff; done < file
打开file
一次并阅读整个循环(包括some_stuff
) 可以从中读取。
Bash 允许你分配一个额外的文件描述符。然后read -u
无需重新打开即可读取它:
exec 17<file # open
read -u 17 a
echo "$a"
read -u 17 a
echo "$a"
read -u 17 a
echo "$a"
exec 17>&- # close
这里17
几乎是任意选择的,它没有什么特殊含义。Bash 可以告诉您打开的文件描述符的最大数量,调用ulimit -n
。在我的 Debian 10 中它是1024
。我可以选择几乎任何小于该值的非负整数,但在您的 Bash 中它可能是512
,因此坚持使用“低”数字更安全。0
,1
和2
分别是 stdin,stdout 和 stderr;255
由 Bash 使用。从技术上讲,可以重定向它们,但在这种情况下,您需要选择一个未使用的号码。Bash 可以为你完成:
每个重定向前面都可以加上文件描述符编号,但也可以加上形式为 的单词
{varname}
。在这种情况下,对于除>&-
和之外的每个重定向操作符<&-
,shell 将分配一个大于 的文件描述符10
并将其赋值给{varname}
。如果>&-
或<&-
前面有{varname}
, 的值varname
定义要关闭的文件描述符。如果{varname}
提供了 ,重定向将超出命令的范围,从而允许 shell 程序员自己管理文件描述符。
以下示例使用此方法:
exec {myfd}<file # open
read -u "$myfd" a
echo "$a"
read -u "$myfd" a
echo "$a"
read -u "$myfd" a
echo "$a"
exec {myfd}>&- # close
unset myfd
这样就不可能选择一个已经在使用的数字;您可能对0
、1
和2
的255
特殊性一无所知。仍然可以选择一个已经在使用的名称,因此问题集中于命名和管理变量。