• shell脚本中使用了管道符,导致变量赋值丢失的原因


    发现这个问题来自对SGE的startmpi.sh脚本做改造的时候。考虑如下一段shell代码: 
    #!/bin/sh
    # declare -i i


    testline
    ="hello:"

    cat testfile 
    | while read line; do
       testline
    ="${testline}${line} "
       echo 
    "In cycle, the testline is: $testline"

    # for (( i=0; i<3; i++ )) do
    #    testline="${testline}${i} "

    #i=0
    #while [ $i -lt 3 ]; do
    #   testline="${testline}${i} "
    #   i=$i+1


    done
    echo 
    $testline

     代码中用到的testfile可以是任何文本的文件,比如: 


    phy2 2 
    phy3 2 
    phy4 2 

    这样的情况下,代码运行的结果出乎我的意料,testline这个变量在while循环中就好像没有被赋过值一样,输出是这样的: 

    In cycle, the testline is: hello:phy2 2 
    In cycle, the testline is: hello:phy2 2 phy3 2 
    In cycle, the testline is: hello:phy2 2 phy3 2 phy4 2 
    hello: 

    这是为什么呢?参考上面的代码,如果把cat testfile | while read line; do这一段注释掉,打开for循环那一段,或打开while循环那一段的话,testline就都能在循环中被赋值,最后的echo $testline就是正确的。这是为什么呢? 

    最后发现是管道符|引发的问题。原因非常简单,之前在学习shell的时候就学过shell执行命令的原理,里面也有对管道的描述。简单来说,在shell中使用管道符号,会产生subshell,从而使在这个subshell中对变量的赋值只在subshell中生效,不会影响到shell脚本本身的进程。 

    但是ksh现在有个feature,能使管道中对变量的赋值反映到父shell中来,这就是网上有人问说这样的代码在k shell中就是OK的原因。 

    附上网上搜来的一篇文章,讲解的不错。

     /Files/super119/bash_pipe_variable_lost.mht.zip

  • 相关阅读:
    企业库连接形式简单例子记录 EnterpriseLibrary.Data
    .net 抽象类(abstract)和接口(interface)区别
    windows service 开发、安装及调试
    asp.net(mvc) 框架
    获取IP地址
    select2 模糊查询远程数据
    设计模式篇——初探命令模式
    初探MVC路由
    初探表达式目录树
    C#实现插入排序法
  • 原文地址:https://www.cnblogs.com/super119/p/1909829.html
Copyright © 2020-2023  润新知