当shell的read遇上while

先看看这个

#!/bin/bash

function a()
{
    while read var
    do
        echo $var
    done < 1.txt
    echo $var
}

a

$ cat 1.txt
hello

1.txt里面只有一个hello,上面的脚本执行之后,第一个echo $var正常打印出了hello,第二个echo $var就是空了。诡异了吧?网上说的都是<,>,|这些符号都是里面都是子进程,while一旦出来之后,变量就没继承了。是吗?看看下面的
function a()
{
    var="firefoxbug"
    while read var
    do
        echo $var
    done < 1.txt
    echo "var = "$var
}

a

结果最后面一个echo还是空,这下子按照子shell解释不了了吧?不信再看看
function a()
{
    var="firefoxbug"
    while read var
    do
        sleep 1000
        echo $var
    done < 1.txt
    echo "var = "$var
}

然后 ps axf | grep bash
1
while里面的sleep是一个shell里面的!再看看这个
function a()
{
    var="firefoxbug"
    cat 1.txt | while read var
    do
        sleep 1000
        echo $var
    done
    echo "var = "$var
}

然后 ps axf | grep bash
2
管道的两边才是子进程,也就是子shell,网上的说法都是不对的。那么到底是怎么回事呢?我们来尝试下这个

echo -n "hello" > 1.txt #去了换行

然后最新的

#!/bin/bash

function a()
{
    while read var
    do
        echo "in loop"
        echo $var
    done < 1.txt
    echo $var
}

a

执行之后会发现 echo "in loop"都没有执行,echo $var出来就是hello。这下子可以可以解释了,问题不是在于重定向,而是在于while和read,read读取一行,一旦发现是EOF了,就立刻break出while了,跳出break再赋值给var的,大概的伪代码是这样的。
while ((c = fgetc(fd)) != EOF )
{
    if (c == '\n')
    {
        print var
    }
    var = var + c
}

标签:Linux, Shell