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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM