理解shell的“ead”命令


Moso31
2025-03-18 08:45:14 (24天前)
  1. 我试图理解UNIX shell,“读取”命令让我感到困惑。如下面的片段(或“while-read”习语)所示,此命令“吃掉”一行标准输入。

(读-r foo; …

2 条回复
  1. 0# WL | 2019-08-31 10-32



    默认行为





    read

    可靠地一次只读取一行,让我们看看其他三个常见命令消耗了多少。

    head -1

    只打印第一行。但是,要做到这一点,它从stdin消耗8192个字节:




    1. $ seq 5000 | tee >(wc >/dev/tty) | ( head -1 >/dev/null; cat) | wc
      5000 5000 23893
      3141 3140 15701
      $ echo $((23893 - 15701))
      8192

    2. </code>


    命令

    awk ‘{exit}’

    应阅读第一行并退出。但是,要做到这一点,它会占用4096字节的stdin:




    1. $ seq 5000 | tee >(wc >/dev/tty) | ( awk ‘{exit}’ >/dev/null; cat) | wc
      5000 5000 23893
      3960 3960 19797
      $ echo $((23893 - 19797))
      4096

    2. </code>



    sed 1q

    应该在第一行读取时退出,但它也消耗4096字节的stdin:




    1. $ seq 5000 | tee >(wc >/dev/tty) | ( sed 1q >/dev/null; cat) | wc
      5000 5000 23893
      3960 3960 19797
      $ echo $((23893 - 19797))
      4096

    2. </code>


    数量8192和4096似乎是当前代码中的缓冲区大小。可以预期这些尺寸可能会从一个版本更改为下一个版本。



    使用stdbuf




    stdbuf

    是试图控制命令使用的缓冲区大小的实用程序。

    stdbuf -i1

    尝试将输入中的缓冲区大小设置为1个字节。使用stdbuf,

    sed 1q

    只消耗一行:




    1. $ (echo First; echo Second) | ( stdbuf -i1 sed 1q>/dev/null; cat)
      Second

    2. </code>




    seq

    作为输入,它仍然只消耗一行:




    1. $ seq 5000 | tee >(wc >/dev/tty) | ( stdbuf -i1 sed 1q >/dev/null; cat) | wc
      5000 5000 23893
      4999 4999 23891

    2. </code>


    这同样的伎俩不起作用

    head

    要么

    awk

    。尽管如此,这两种方法都会消耗几个kB

    stdbuf





    1. $ 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

    2. </code>


    摘要



    虽然壳内置

    read

    可靠地一次仅消耗一行,外部命令,如

    sed



    awk

    ,和

    head

    ,即使在处理单行时,也会消耗依赖于实现的stdin量。



    回答你的两个问题:





    1. 在当前的实现中,可以只使用一行stdbuf

      stdbuf -i1 sed 1q

      但似乎没有任何保证,这将继续适用于任何未来的版本。





    2. 的例子

      stdbuf -i1 sed 1q

      表示可以编写一个关闭输入缓冲的实用程序,因此只消耗所需的stdin。



    3. </醇>

登录 后才能参与评论