Bash while-read循环的一个问题

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 必须保

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
必须保留这些回音,因为它们是在标准输出上提供输出的其他脚本的替代品,但它们给出的结果完全相同。缺少一些应打印的值


提前感谢大家。

让我们仔细看看这一行:

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($#));然后
。但因为我不知道你想做什么,我不能提供一个明确的解决方案

虽然在这种情况下,修复
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($#));然后
。但由于我不知道你想做什么,我不能提供一个明确的答案