假设我们有一个文件,其中的数字1到5是逐行写的,当我打开一个文件作为标准输入并使用“while read”时,可以读取stdin的命令无法读取该文件的第一行。$ while read x; do sed ''; done<file
2
3
4
5
使用哪个命令没有区别:sed、awk、cat等。如果命令能够从stdin读取,就会出现这个问题。我使用的shell之间也没有区别。我在sh、bash和zsh中尝试了同样的操作,结果完全相同。
值得注意的是,循环迭代了5次,每行一次,例如:$ while read x; do printf 'something\n'; done<file
一些东西
一些东西
一些东西
一些东西
一些东西
我知道如果我想正确地读取所有行,我必须在read命令中指定一个变量,然后将其传递给命令。但是我试图弄清楚这里发生了什么。为什么当我没有直接为命令指定input时会出现这个问题?也许这是一个没有功能目的的副作用。
我找不到任何有关"while read“语句这种行为的信息,也找不到任何有类似问题的人。
2条答案
按热度按时间1cklez4t1#
您的代码只迭代 * 一次 *。
...行为如下:
file
打开并连接到标准输入read
使用stdin文件的第一行,并将其放入$x
sed ''
从stdin中消耗 * 文件的整个剩余部分 *,并将其打印到stdout,不做任何更改。read
发现没有更多的数据(因为sed
已经用完了所有数据),循环结束。如果希望
sed
只对read x
使用的一行进行操作,并防止其他错误,可以改为:变更:
IFS=
可防止read
删除前导或尾随空格。-r
参数可防止read
使用反斜杠。printf '%s\n' "$x"
到sed
的管道传输改变了sed
的stdin,使得它不包含 * 文件的其余部分 *,而是仅包含一行。因此,这确保了sed
正在处理由read
消耗的行。而不是忽略该行并处理文件的整个其余部分。(使用printf
代替echo
是一个正确性问题;请参见UNIX & Linux Stack Exchange上的Why is printf better than echo?)。nwwlzxa72#
stdin
的第一行没有丢失,而是在使用重定向操作符'<'
将文件内容重定向到while循环时由shell使用。第一行用作初始化while循环的输入,后续行在循环内部读取。这就是为什么循环内部的命令不处理第一行的原因。为了避免这种情况,您可以使用'<&'
将文件重定向到新的文件描述符,如下所示: