【问题标题】:Can the leading bytes of an input stream be copied to another file without closing the input stream?可以将输入流的前导字节复制到另一个文件而不关闭输入流吗?
【发布时间】:2012-03-05 18:30:45
【问题描述】:

我基本上是在问为什么:

head -c 2 > /tmp/first-two-bytes
cat /tmp/first-two-bytes -

不会将 stdin 的前两个字节复制到 /tmp/first-two-bytes,然后将 stdin 的全部内容转储到 stout。

[编辑]为了清楚起见,这是我的机器上发生的事情:

$ uname -a
Darwin Myles-Byrnes-iMac.local 11.3.0 Darwin Kernel Version 11.3.0: Thu Jan 12 18:47:41 PST 2012; root:xnu-1699.24.23~1/RELEASE_X86_64 x86_64
$ echo "hello, world" | (head -c 2 > /tmp/first-two-bytes; cat /tmp/first-two-bytes -)
he$ cat /tmp/first-two-bytes 
he$

【问题讨论】:

  • 它可以满足您对我的期望。你要向标准输入发送什么?
  • 也适用于我,但请参阅下面的回复。
  • 出于好奇,如果你有超过 8K 的输入,你会得到多少输出?我猜 head 会读取 4K 或 8K 的数据,如果你有足够的输入,猫会得到一些。
  • 威廉:是的。刚刚在一个更大的文件上尝试过,这正是正在发生的事情。该死的

标签: bash stdin head


【解决方案1】:

您的命令完全按照应有的方式执行。请记住,流不是文件。无论从流中读取什么,都会从中删除。没有倒带(除非您在应用程序中使用缓冲区自己实现它 - 但它将在应用程序中,而不是流的属性)。第一个命令从标准输入读取 2 个字节。另一个从 /tmp 输出文件和“stdin 的全部内容”——但在调用它时,stdin 的“全部内容”已经比执行前一个命令之前少了两个字节。

【讨论】:

  • 对。这正是我所期望的,但它对我不起作用:(
  • 不幸的是,我无法在我的机器上重现此行为。也许达尔文的头脑(双关语)有些不同?我不知道他们是使用 GNU coreutils 还是有自己的。 head --version 说什么?
【解决方案2】:

从下面的命令可以看出,行为和你描述的一样:

$ echo "hello, world" | (head -c 2 > /tmp/first-two-bytes; cat /tmp/first-two-bytes -)
hello, world
$ cat /tmp/first-two-bytes
he$

注意最后一个$是提示符

【讨论】:

    【解决方案3】:

    流中的每个字节只能读取一次。完全有可能实现 head 以使其仅读取 2 个字节,但也可以实现 head 以读取整个流并仅输出前 2 个字节。如果使用后一种实现,则 stdout 将在 cat 看到任何数据之前耗尽。

    如果您希望 head 的功能能够保证从输入流中准确读取 2 个字节的数据并且具有最大的可移植性,您可能需要使用 dd。只需将head -c 2 替换为dd bs=2 count=1

    【讨论】:

    • 我看到后一种情况的行为
    • @quackingduck 这意味着您的 head 实现正在从输入流中读取所有数据,这对于 head 来说是完全有效的行为。如果您想要一个从流中准确读取两个字符的程序,请尝试: perl -e 'sysread STDIN, $v, 2;打印 $v'
    • 谢谢威廉。我试图避免对脚本语言的任何依赖,因为我打算打包分发脚本。
    • @quackingduck 您可以使用 dd:'dd bs=2 count=1' 将从输入流中读取 2 个字节,并且无处不在。
    【解决方案4】:

    如果我理解正确,您只想将标准输入的前两个字节写入一个特殊文件,然后将整个输入(包括前两个字节)打印到标准输出。

    我会这样做:

    while read -r -n2 c2; do
        if [ ! -f tmp.txt ]; then
            echo $c2 > tmp.txt
        fi
        echo $c2
    done < input.txt
    

    基本上你首先将输入读入一个变量,一次两个字节,然后只写入前两个字节。

    【讨论】:

    • 感谢您的回答 Manish。在这种情况下,我正在寻找一种不会将所有标准输入读入内存的解决方案。
    • @quackingduck 现在更新了它,它可以逐行读取输入。
    • 嗨,Manish,再次感谢您查看此内容。我曾考虑使用 read 但我担心它不会是二进制安全的。我真的想读取前两个字节,而不是前两个字符。该程序将接收二进制文件作为输入。
    • @quackingduck 好的,我不知道这是一个二进制文件。我已经更新了我的答案。您可以使用read -r -n2 一次最多读取两个字节。
    猜你喜欢
    • 2015-05-14
    • 1970-01-01
    • 1970-01-01
    • 2017-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-19
    • 1970-01-01
    相关资源
    最近更新 更多