shell指令碼中while重定向的乙個坑

2021-08-14 16:48:27 字數 2115 閱讀 7311

假設我有乙個需求:從data.txt裡按行讀取乙個檔案,按格式"[行號]內容"輸出,再輸出讀取的行數。

data.txt:

youth is not a time.

it is a state of mind.

oh, you are right.

很簡單:

#!/bin/bash

i=0cat 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

dosleep 1

done

done

言簡意賅,讓外層迴圈先跑起來,20s後,內迴圈開始跑,內迴圈就是使用管道。

$sh test.sh

20sne立刻檢視程序

$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=0while 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------------------------------------

最後,乙個for迴圈也可以達到效果,而且貌似這種速度更快:

for line in `cat data.txt`

do echo $line

done

搞定,收工!

while命令 shell指令碼

while test command do other commands donewhile 命令中定義的test command和if then語句的格式一模一樣。可以使用任何普通的bash shell命令,或者用test命令進行條件測試,比如測試變數值。while命令的關鍵在於所制定的test ...

Shell指令碼程式設計while迴圈

while 語句 do 執行語句 done接下來將會通過兩個簡單並且經常的使用的例子講解 bin bash i 1while i le 10 do i expr i 1 done echo i其中lele le表示不大於,exp rexpr expr 表示是相加運算 原始檔為 1 192.168.1...

shell 指令碼while迴圈和for迴圈

1.1 while 當條件為真時就進行迴圈,條件不成立時退出 提示使用者輸入 y 或 y 來終止程式。a用在判斷式中表示 and bin bash while aa y a aa y do read p please input y y to stop this program aa done1.2...