当前位置: 首页 > 面试题库 >

为什么在bash的while读取循环内重定向stdin?

奚光霁
2023-03-14
问题内容

考虑以下 示例 脚本:

#!/bin/sh

do_something() {
    echo $@
    return 1
}

cat <<EOF > sample.text
This is a sample text
It serves no other purpose
EOF

cat sample.text | while read arg1 arg2 arg3 arg4 arg5; do
    ret=0
    do_something "$arg1" "$sarg2" "$arg3" "$arg4" "$arg5" <&3 || ret=$?
done 3<&1

重定向stdout作为文件描述符3的输入的目的是什么?至少在中Bash,如果省略,似乎没有什么区别。如果在非shell中执行它,是否有效果bash

更新

对于那些想知道它来自哪里的人,它是Debian
cryptdisks_start脚本的简化示例。


问题答案:

此处的明确意图是通过确保其stdin来自其他位置来防止do_somethingsample.text流中读取。
如果没有看到重定向或不重定向的行为差异,那是因为do_something在测试中实际上没有从stdin读取数据。

如果您同时拥有两者readdo_something从同一流中读取内容,则do_something的后续实例将无法使用消耗的任何内容,read并且,当然,您将在输入到时输入非法内容do_something,从而导致诸如尝试使用错误的加密密钥(如果实际用例是cryptmount),&c。

cat sample.text | while read arg1 arg2 arg3 arg4 arg5; do
    ret=0
    do_something "$arg1" "$sarg2" "$arg3" "$arg4" "$arg5" <&3 || ret=$?
done 3<&1

现在,它有很多错误- 3<&1与相比是一种不好的做法3<&0,因为它假设没有基础就可以将stdout用作输入内容-但它 确实 可以实现该目标。

顺便说一下,我会这样写:

exec 3</dev/tty || exec 3<&0     ## make FD 3 point to the TTY or stdin (as fallback)

while read -a args; do           ## |- loop over lines read from FD 0
  do_something "${args[@]}" <&3  ## |- run do_something with its stdin copied from FD 3
done <sample.text                ## \-> ...while the loop is run with sample.txt on FD 0

exec 3<&-                        ## close FD 3 when done.

它有点冗长,需要显式关闭FD3,但这意味着如果我们将stdout连接到FIFO的只写侧(或任何其他只写接口)运行,我们的代码就不会再被破坏。而不是直接发送给TTY。



 类似资料:
  • 问题内容: 我一生无法理解为什么我无法在while循环之外阅读postPrioity。我尝试过“ export postPrioity =“ 500””仍然无法正常工作。 有任何想法吗? -或在计划文字中- 输出:(我在files.txt中只有3个文件名) 问题答案: 管道操作员创建一个子外壳,请参阅BashPitfalls和BashFAQ。解决方案:不要使用,反正毫无用处。

  • 我想我的程序跳过了while循环,但我真的不确定到底发生了什么。该函数应该通过找到GCD,然后将分子和分母除以该数字来减少分数。 我得到分子和分母的绝对值,以确保如果分数是负数,我会在最后保持它。如果分子为0,则要求我返回(0,1)。问题是关于while循环。。。似乎它被完全跳过了。有什么建议吗?

  • 问题内容: 以下示例在Node.js书中给出: 解释了while循环为何阻止执行时,作者说: 节点将永远不会执行超时回调,因为事件循环卡在了循环中,而循环在第7行开始了,因此永远不会给它处理超时事件的机会! 但是,作者没有解释为什么这是在事件循环的背景下发生的,还是在幕后真正发生了什么。 有人可以详细说明吗?为什么节点卡住?以及如何在保留控制结构的同时更改上述代码,以使事件循环不会被阻塞,并且代码

  • 问题内容: 一个简单的测试脚本在这里: 当我这样做时,CPU锁定为100%,它每秒可以处理大约1000行。大约需要5分钟来处理`cat my450klinefile.txt /dev/null`半秒钟内的操作。 有没有一种 更有效的方法 来执行此操作。我只需要从stdin中读取一行,计算字节数,然后将其写到命名管道中即可。但是,即使这个例子的速度也不可能太慢。 每输入1 Gb输入行,我需要执行一些

  • 我正在写一份简单的银行申请书。在我的程序中,我使用了while循环。如果用户输入错误,它将再次提示用户输入。 现在的问题是我无法编写任何语句。它总是显示错误(比如:unreachable语句),最终该行不会被打印出来。 我该怎么解决这个问题? [我之所以需要使用,是因为我想打印用户输入的所有信息。] 我正在从事的项目:

  • 问题内容: 我一直在使用“ if”来测试自己的版本,并且一切似乎都正常。当然,如果使用signalAll()而不是signal(),这将导致严重崩溃,但是如果一次仅通知一个线程,这怎么会出错? 他们的代码在这里 -检查put()和take()方法;在Condition的JavaDoc顶部可以看到一个更简单,更重点的实现。 下面是我实施的相关部分。 PS我知道,通常,尤其是在这样的lib类中,应该让