每秒通过管道将数据传送到带有 EOF 的 fifo

每秒通过管道将数据传送到带有 EOF 的 fifo

我正在尝试将一些原始二进制数据通过管道传输到 fifo (out.pipe),并确保定期发送 EOF。我不明白为什么以下行不会执行我想要的操作:

while true; do read -t 1 -N 128 line; echo -n $line > out.pipe; done

当超时发生时,看起来好像$line被赋予了一个空值,即使没有发生,所有换行符也会从输入中删除。这不是我对应该发生的事情的理解这个文件:

-N 个字符

read 在精确读取 nchars 个字符后返回,而不是等待完整的输入行,除非遇到 EOF 或读取超时。输入中遇到的分隔符不会被特殊处理,并且不会导致 read 返回,直到读取 nchars 字符。

-t 超时

如果在超时秒内未读取完整的输入行(或指定数量的字符),则会导致读取超时并返回失败。 timeout 可以是小数点后带有小数部分的十进制数。仅当 read 正在从终端、管道或其他特殊文件读取输入时,此选项才有效;从常规文件读取时它没有效果。如果读取超时,读取会将读取的任何部分输入保存到指定的变量名称中。如果超时为0,则read立即返回,而不尝试读取数据。如果输入在指定的文件描述符上可用,则退出状态为 0,否则为非零。如果超过超时,则退出状态大于 128。

没有-N 128上的参数read,以及-n上的参数echo,这非常接近我想要的。问题是换行符被特殊对待,即使没有数据通过也会被发送:

while true; do read -t 1 line; echo $line > out.pipe; done

我一直在用以下行测试进入我的管道的内容:

while true; do cat out.pipe; done

我测试过通过 stdin 发送输入以及通过 with 发送 HTTP 数据echo -e "GET / HTTP/1.1\r\nHost: hostname\r\n\r\n" | nc localhost 80 | myreadcommand,由于孤独的\r字符,这非常令人困惑。

我不明白什么?有没有更好的方法来做到这一点,我缺少什么?

答案1

read的手册页还说:

应从输入中删除终止符<newline>(如果有),并将结果拆分为字段,就像 shell 中参数扩展结果一样

它还根据您传递给它的关于如何处理新行的参数记录了许多异常。如果此类例外对您很重要,则有必要阅读整个手册页。

如果您想忽略某些字符,例如\r,可以轻松完成sed

echo "hi\r\nI am a script" | sed "s/\r//g"

为了使替换更加明显,您可以将其替换为其他内容,例如:

echo "hi\r\nI am a script" | sed "s/\r/,/g"

同样重要的是要注意,使用-e参数 forecho使其解释反斜杠特殊字符组合,这些组合实际上并不对应于输入中存在的真实换行字符。

相关内容