Bash while-read循环的一个问题
while循环工作的一点是 我有以下代码:Bash while-read循环的一个问题,bash,Bash,while循环工作的一点是 我有以下代码: f2(){ if [[ -t 0 ]] ; then echo "$*" ; else echo $(cat) ; fi ; } echo -e 'a\nb\nc' | while read var ; do f2 $var ; done 我感兴趣的是为什么“a”字母没有打印出来。 然而,如果我使用for循环,一切似乎都按预期工作。 像这样: for var in `echo -e 'a\nb\nc'`; do f2 $var ; done 必须保
f2(){ if [[ -t 0 ]] ; then echo "$*" ; else echo $(cat) ; fi ; }
echo -e 'a\nb\nc' | while read var ; do f2 $var ; done
我感兴趣的是为什么“a”字母没有打印出来。
然而,如果我使用for循环,一切似乎都按预期工作。
像这样:
for var in `echo -e 'a\nb\nc'`; do f2 $var ; done
必须保留这些回音,因为它们是在标准输出上提供输出的其他脚本的替代品,但它们给出的结果完全相同。缺少一些应打印的值
提前感谢大家。让我们仔细看看这一行:
echo -e 'a\nb\nc' | while read var ; do f2 $var ; done
即:
- 创建管道
- 启动子进程以运行
命令,将其标准输出重定向到管道echo
- 启动子进程以运行
命令,将其stdin重定向到管道while
readlink -f /dev/stdin
readlink-f/dev/stdin
(无论如何,在Linux上)将告诉我们stdin的解析是什么。在交互式shell中,它将显示stdin
是一个终端:
$ readlink -f /dev/stdin
/dev/pts/14
现在,让我们回到管道:
$ echo | readlink -f /dev/stdin
/proc/28050/fd/pipe:[608866]
正如所料,stdin
是一个管道
现在,管道的实际右侧是:
| while read var ; do f2 $var ; done
其中f2
首先检查if[[-t0]]
:换句话说,f2检查stdin
是否为终端。我们可以看到stdin
不是终端,因此f2
将继续执行else
子句:
echo $(cat)
它打印stdin的其余部分,用空格替换行尾。stdin
重定向最初是三行,a
、b
和c
,但是read
已经读取了第一行,所以剩下的是b
和c
,这就是cat
将返回的内容
不用说,逻辑是错误的。为什么要f2
检查其输入是否已重定向
更正常的做法可能是检查是否有任何参数:if($#));然后
。但因为我不知道你想做什么,我不能提供一个明确的解决方案
虽然在这种情况下,修复f2
可能更好,但通过使用进程替换和不同的文件描述符,可以避免在读取时对循环使用stdin
:
while read -u3 var ; do f2 $var ; done 3< <(echo $'a\nb\nc')
读取时-u3变量;不做f2$var;完成3<让我们仔细看看这一行:
echo -e 'a\nb\nc' | while read var ; do f2 $var ; done
即:
- 创建管道
- 启动子进程以运行
echo
命令,将其标准输出重定向到管道
- 启动子进程以运行
while
命令,将其stdin重定向到管道
因此,让我们使用这个有用的工具,将其简化为要点:
readlink -f /dev/stdin
readlink-f/dev/stdin
(无论如何,在Linux上)将告诉我们stdin的解析是什么。在交互式shell中,它将显示stdin
是一个终端:
$ readlink -f /dev/stdin
/dev/pts/14
现在,让我们回到管道:
$ echo | readlink -f /dev/stdin
/proc/28050/fd/pipe:[608866]
正如所料,stdin
是一个管道
现在,管道的实际右侧是:
| while read var ; do f2 $var ; done
其中f2
首先检查if[[-t0]]
:换句话说,f2检查stdin
是否为终端。我们可以看到stdin
不是终端,因此f2
将继续执行else
子句:
echo $(cat)
它打印stdin的其余部分,用空格替换行尾。stdin
重定向最初是三行,a
、b
和c
,但是read
已经读取了第一行,所以剩下的是b
和c
,这就是cat
将返回的内容
不用说,逻辑是错误的。为什么要f2
检查其输入是否已重定向
更正常的做法可能是检查是否有任何参数:if($#));然后
。但因为我不知道你想做什么,我不能提供一个明确的解决方案
虽然在这种情况下,修复f2
可能更好,但通过使用进程替换和不同的文件描述符,可以避免在读取时对循环使用stdin
:
while read -u3 var ; do f2 $var ; done 3< <(echo $'a\nb\nc')
读取时-u3变量;不做f2$var;完成3<让我们仔细看看这一行:
echo -e 'a\nb\nc' | while read var ; do f2 $var ; done
即:
- 创建管道
- 启动子进程以运行
echo
命令,将其标准输出重定向到管道
- 启动子进程以运行
while
命令,将其stdin重定向到管道
因此,让我们使用这个有用的工具,将其简化为要点:
readlink -f /dev/stdin
readlink-f/dev/stdin
(无论如何,在Linux上)将告诉我们stdin的解析是什么。在交互式shell中,它将显示stdin
是一个终端:
$ readlink -f /dev/stdin
/dev/pts/14
现在,让我们回到管道:
$ echo | readlink -f /dev/stdin
/proc/28050/fd/pipe:[608866]
正如所料,stdin
是一个管道
现在,管道的实际右侧是:
| while read var ; do f2 $var ; done
其中f2
首先检查if[[-t0]]
:换句话说,f2检查stdin
是否为终端。我们可以看到stdin
不是终端,因此f2
将继续执行else
子句:
echo $(cat)
它打印stdin的其余部分,用空格替换行尾。stdin
重定向最初是三行,a
、b
和c
,但是read
已经读取了第一行,所以剩下的是b
和c
,这就是cat
将返回的内容
不用说,逻辑是错误的。为什么要f2
检查其输入是否已重定向
更正常的做法可能是检查是否有任何参数:if($#));然后
。但由于我不知道你想做什么,我不能提供一个明确的答案