bash 中子 shell 位置错误

bash 中子 shell 位置错误

我遇到了 bash 中一个不幸的错误功能问题,如下面这个功能所示:

trying ()
{
    res=0;
    echo $res;
    cat some_text_file | while read op rpt rec; do
        res=1;
        echo $res;
    done;
    echo $res
}

我原本期望最后echo $res打印的是1- 但是,它打印的是0。原因是以 开头的循环cat some_text_file | while read op rpt rec; do在子 shell 中运行,而在 ksh 中则不会。

对于这个简单案例的解决方法是:

trying ()
{
    res=0;
    echo $res;
    while read op rpt rec; do
        res=1;
        echo $res;
    done < some_text_file;
    echo $res
}

然而,在大多数情况下,它更像是cat some_file | awk '{...}' | while read ...,我真的不想为此创建一个临时文件;它应该可以工作。

不幸的是,我的服务器上使用的是 bash,否则到处都会是 ksh。那么,有什么好方法可以解决这个问题吗?

答案1

有几种解决方法:

  1. 您可以激活shopt -s lastpipe以获得类似 ksh 的行为。这仅在禁用作业控制的情况下有效 - 即您始终可以在独立脚本中使用此选项,但在使用交互式 shell 时,它只会影响(子 shell内的管道)

  2. 如果变量只需要短暂存在(并且除了 'while' 循环之外没有任何东西需要读取 stdin),你可以通过管道连接到命令列表

    cat some_file | awk '{...}' | {
        res=0
        echo $res
        while read op rpt rec; do
            res=1
            echo $res
        done
        echo $res
    }
    
  3. 你可以使用 bash 的流程替代操作符<(...)从子 shell 中读取,就像它是一个命名文件一样,包括将其重定向到“while”循环:

    res=0
    echo $res
    while read op rpt rec; do
        res=1
        echo $res
    done < <(cat some_file | awk '{...}')
    echo $res
    
  4. 您已经在使用 awk...

    cat some_file | awk '{...}' | awk '
       BEGIN { res = 0 }
       { res = 1 }
       END { print res }
    '
    

相关内容