你好,游客 登录 注册 搜索
背景:
阅读新闻

shell中while循环的陷阱

[日期:2017-08-28] 来源:cnblogs.com/f-ck-need-u  作者:f-ck-need-u [字体: ]

在写while循环的时候,发现了一个问题,在while循环内部对变量赋值、定义变量、数组定义等等环境,在循环外面失效。

一个简单的测试脚本如下:

#!/bin/bash
echo "abc xyz" | while read line
do
    new_var=$line
done
echo new_var is null: $new_var?

执行结果证明,$new_var的结果是空值。在google上查了查,才发现问题出在管道上。

先看看下面的内容。

while循环的写法有好几种,它的语法结构为:

while test_cmd_list; do cmd_list; done

但更经常地,while循环更多地用于读取标准输入的内容来实现循环。有以下几种写法:

写法一:使用管道传递内容,这是用的最多、但却最烂的写法

echo "abc xyz" | while read line  

do 

    ...

done

写法二:

while read line

do

    ...

done <<< "abc xyz"

写法三:从文件中读取内容

while read line

do

    ...

done </path/filename

方法四:采用进程替换

while read var

do

    ...

done < <(cmd_list)          

方法五:改变标准输入

exec <filename

while read var

do

    ...

done        

尽管写法有多种,但它们并不等价。方法一中使用的是管道符号,这使得while语句在子shell中执行,这意味着while语句内部设置的变量、数组、函数等在循环外部都不再生效。这正是文章开头所说的陷阱。更简单的:echo haha | a=5,在命令执行结束后,变量a的值也不再是5。其余4种写法,while语句都不在子shell中执行,因此都不会出现文章开头所说的问题。

例如,使用写法二的here string代替写法一:

#!/bin/bash
while read line
do
    new_var=$line
done <<< "abc xyz"
echo new_var is null: $new_var?

或者使用写法四的进程替换:

#!/bin/bash
while read line
do
    new_var=$line
done < <(echo "abc xyz")
echo new_var is null: $new_var?

由此可以说,在上面的5种写法中,使用的最广泛的写法一虽然最简单、方便,但其实是最烂的一种。

本文永久更新链接地址http://www.linuxidc.com/Linux/2017-08/146534.htm

linux
相关资讯       while循环 
本文评论   查看全部评论 (0)
表情: 表情 姓名: 字数

       

评论声明
  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款