while read LINE 只读一行就结束的问题

问题

   tt.log文件内容

         14 1048576000 /usr/oracle/data/PRD0.2/store_ix10.dbf   INDICES
         14  367001600 /usr/oracle/data/PRD0.2/store_ix11.dbf   INDICES
         14 1258291200 /usr/oracle/data/PRD0.3/store_new.dbf    STORE_NEW
         18 1048576000 /usr/oracle/data/PRD0.2/store_ix10.dbf   INDICES
         18  367001600 /usr/oracle/data/PRD0.2/store_ix11.dbf   INDICES
         18  157286400 /usr/oracle/data/PRD0.2/store_ix12.dbf   INDICES

我想从tt.log文件中取出1,3列来执行rexec命令,写了ta.sh执行文件,内容如下:

while read t1 t2 t3 t4
do
echo $t2 $t4
rexec lshas$t1 "ls -lt $t3|awk '{print \$5,\$9}' "
done <tt.log

#bash -x ta.sh

执行顺序如下:
+ 0< tt.log
+ read t1 t2 t3 t4
+ echo 1048576000 INDICES
1048576000 INDICES
+ rexec lshas10 ls -lt /usr/oracle/data/PRD0.2/store_ix10.dbf|awk '{print $5,$9}'
1048580096 /usr/oracle/data/PRD0.2/store_ix10.dbf
+ read t1 t2 t3 t4
不读第二行,请高手指教。

原因:

循环中的重定向
或许你应该在其他脚本中见过下面的这种写法:
while read line
do
       …
done < file
刚开始看到这种结构时,很难理解< file是如何与循环配合在一起工作的。因为循环内有很多条命令,而我们之前接触的重定向都是为一条命令工作的。
这里有一个原则,这个原则掌握好了,这个问题就很简单了:
对循环重定向的输入可适用于循环中的所有需要从标准输入读取数据的命令;
对循环重定向的输出可适用于循环中的所有需要向标准输出写入数据的命令;
当在循环内部显式地使用输入或输出重定向,内部重定向覆盖外部重定向。

因为在while循环体中不只有read还有rexec都会从标准输入(即tt.log)中读取数据,于是read从标准输入中读取了一行内容后,rexec读取了剩下的所有内容,while也就结束了。那么这个问题怎么解决呢?

1.让read和rexec分别从不同的输入中读取内容,我们知道在shell中标准输入的文件描述符FD是1,那我们让tt.log与其它FD(比如3)绑定,然后read就是从&3中读取数据rexec还是从&1中读取。在shell中,有一个命令可以实现绑定重定向

绑定输入重定向

exec 文件描述符[n] <[ file|文件描述符|设备]

绑定输出重定向

 

exec 文件描述符[n] >[ file|文件描述符|设备]

关闭绑定重定向

exec n <|> &-

解决方法:

exec 3<tt.log #绑定tt.log到3号fd

while read -u3  t1 t2 t3 t4

do

echo $t2 $t4

rexec lshas$t1 "ls -lt $t3|awk '{print \$5,\$9}' "

done

exec 3<&-  #关闭3号fd

#######################################################################

read -u3 i 的意思是从 3 号 fd (file descriptor,文件描述符) 中读一行数据到 i 变量中

原来的情况是     FD1 ===>read                    FD1 ===>rexec

修改后的情况是 FD3 ===>read                    FD1 ===>rexec

 

posted @ 2018-03-08 12:06  wangyi429111  阅读(1910)  评论(0编辑  收藏  举报