shell编程--while循环和管道符的迷雾

最近要写一个简单的shell,批量读取一个文本中的数据,插入到db中,并输出插入的条数。读取使用了管道+while方式,问题来了,脚本执行完毕,数据插入正常,但是最后统计的却是插入0行,好奇怪!
撇开我的问题不说,且看下面一个例子。
假设我有一个需求:从data.txt里按行读取一个文件,按格式"[行号]内容"输出,再输出读取的行数。

data.txt:
youth is not a time.
it is a state of mind.
oh, you are right.
有人说,很简单呀,看我啪啪啪,敲了几行:
#!/bin/bash
i=0
cat data.txt | while read line
do
  i=`expr $i + 1`
  echo “[$i]$line"
done

echo $i 
执行的结果却令人大吃一惊:
-----输出结果----------------------
[1]youth is not a time.
[2]it is a state of mind.
[3]oh, you are right.
0
------------------------------------
为什么是1?明明有3行的,应该是3啊!!!

原因就是:当while遇到管道的时候,循环体会被fork到另一个子shell去执行,此时while中i被改变,然而循环退出时,父shell的i并没变,依旧是0,故而会输出0。
什么?你不信?那么我们试试这个shell:
#!/bin/bash
while true
do
  sleep 20
  cat data.txt | while read line
  do
    sleep 1
  done
done
言简意赅,让外层循环先跑起来,20s后,内循环开始跑,内循环就是使用管道。
$sh test.sh
立刻查看进程
$ps aux | grep sh
可以看到有如下进程:
----输出结果--------------------------
kyle     22777  0.0  0.0   2216   540 pts/0    S+   12:30   0:00 sh tread.sh
---------------------------------------
20s后,再次查看:
$ps aux | grep sh
----输出结果--------------------------
kyle     22777  0.0  0.0   2216   540 pts/0    S+   12:30   0:00 sh tread.sh
kyle     22797  0.0  0.0   2216   540 pts/0    S+   12:30   0:00 sh tread.sh
---------------------------------------
这下知道了为什么i的值为0了吧。

-------------------------------------我是分割线---------------------------
如何避免以上情况?
答案:不要使用管道。
那用什么?
答案:使用重定向。
#!/bin/bash
i=0
while read line
do
  i=`expr $i + 1`
  echo "[$i]$line"
done < data.txt

echo $i

再次运行:
-----输出结果----------------------
[1]youth is not a time.
[2]it is a state of mind.
[3]oh, you are right.
3
------------------------------------
搞定,收工!





  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值