了解外壳的“读取”命令

时间:2019-03-03 19:17:21

标签: shell unix sh

我试图了解UNIX Shell,“ read”命令使我感到困惑。如以下代码段(或“ while-read”惯用语)所示,此命令“占用”一行标准输入。

(read -r foo ; echo '*** Before cat ***' ; cat) << 'END'
hello
world
END

输出: *** Before cat *** world 我的问题如下:

  1. 有人知道其他命令具有相同的行为,即仅消耗一行标准输入,而不消耗全部输入吗?
  2. 是否可以在不读取shell的情况下编写具有类似行为的命令?

1 个答案:

答案 0 :(得分:0)

默认行为

虽然Nothing一次只能可靠地读取一行,但让我们看一下其他三个普通命令的消耗量。 read仅打印第一行。但是,这样做会消耗stdin的8192字节:

head -1

命令$ seq 5000 | tee >(wc >/dev/tty) | ( head -1 >/dev/null; cat) | wc 5000 5000 23893 3141 3140 15701 $ echo $((23893 - 15701)) 8192 应该读取第一行并退出。但是,为此,它消耗了4096个字节的stdin:

awk '{exit}'

$ seq 5000 | tee >(wc >/dev/tty) | ( awk '{exit}' >/dev/null; cat) | wc 5000 5000 23893 3960 3960 19797 $ echo $((23893 - 19797)) 4096 应该在读取的第一行中退出,但它也会消耗4096字节的stdin:

sed 1q

数量8192和4096在当前代码中似乎是缓冲区大小。可能希望这些大小可以从一个版本更改为下一个版本。

使用stdbuf

$ seq 5000 | tee >(wc >/dev/tty) | ( sed 1q >/dev/null; cat) | wc 5000 5000 23893 3960 3960 19797 $ echo $((23893 - 19797)) 4096 是一种实用程序,可尝试控制命令使用的缓冲区大小。 stdbuf尝试将输入中的缓冲区大小设置为1个字节。应用stdbuf后,stdbuf -i1仅消耗一行:

sed 1q

使用$ (echo First; echo Second) | ( stdbuf -i1 sed 1q>/dev/null; cat) Second 作为输入,它仍然只消耗一行:

seq

同一技巧不适用于$ seq 5000 | tee >(wc >/dev/tty) | ( stdbuf -i1 sed 1q >/dev/null; cat) | wc 5000 5000 23893 4999 4999 23891 head。尽管有awk,这两个都将消耗数kB:

stdbuf

摘要

尽管内置$ seq 5000 | tee >(wc >/dev/tty) | ( stdbuf -i1 head -1 >/dev/null; cat) | wc 5000 5000 23893 3141 3140 15701 $ echo $((23893 - 15701)) 8192 $ seq 5000 | tee >(wc >/dev/tty) | ( stdbuf -i1 awk '{exit}' >/dev/null; cat) | wc 5000 5000 23893 3960 3960 19797 $ echo $((23893 - 19797)) 4096 的外壳一次仅可靠消耗一行,但是外部命令(例如readsedawk)消耗的是实现相关的数量即使处理一行时也是如此。

要回答您的两个问题:

  1. 在当前实现中,可以使用head仅消耗一行stdbuf,但是似乎没有保证在任何将来的版本中都可以继续使用。

    < / li>
  2. stdbuf -i1 sed 1q的示例表明,可以编写一种实用程序来关闭输入缓冲,因此仅消耗所需的stdin。