空字符串与空文件的差异及相关读写问题
Bash中read命令的行为差异与问题解答
先解释你观察到的现象:read -r命令的退出逻辑是:
若读取到完整的一行(即使内容为空,只要有换行符结尾),返回退出状态0,执行循环体;
若直接遇到EOF且未读取到任何字符,返回非0,循环终止。
<<< ''是here-string语法,Bash会自动在传入的字符串末尾追加一个换行符,相当于给read提供了一个空行(内容为空,但有换行结束)。因此read能读到空字符串foo,退出状态0,循环执行一次,输出${#foo}即0。/dev/null是完全空的文件,没有任何字符(包括换行符),read一启动就遇到EOF,未读取到任何内容,退出状态非0,循环直接不执行,所以无输出。
问题1:是否存在一种字符串字面量,使得无法从中读取哪怕一次数据?
如果限定使用<<<(here-string)语法,不存在这样的字面量——因为Bash对所有here-string都会强制追加换行符,read总能读到至少一个空行,循环必然执行一次。
但如果允许其他输入方式,比如通过进程替换或管道传入不带换行的空字符串,就能让read一次都不读取:
# 用进程替换传入空内容(无换行) while read -r foo; do echo ${#foo}; done < <(printf '') # 或用管道 printf '' | while read -r foo; do echo ${#foo}; done
这里的''就是空字符串字面量,由于输入没有任何字符(包括换行),read直接遇到EOF,退出状态非0,循环完全不执行。
问题2:文件需要包含什么内容,才能恰好从中读取到一个空字符串且无其他内容?
文件需要仅包含一个换行符(即一个空行)。
当read读取这个文件时:
- 第一次读取:读到换行符之前的空内容,将
foo设为空字符串,退出状态0,执行循环体(输出0); - 第二次读取:此时已经到文件末尾,遇到EOF,退出状态非0,循环终止。
如果文件是空的(无任何字符),read直接EOF,不会执行循环;如果文件有多个换行符,会读取多次空字符串,不符合“恰好读取一次”的要求。
内容的提问来源于stack exchange,提问作者KraftDurchBlumen
相关产品推荐
相关产品推荐

