舉個例子來說好了:
foo=bar while read line do # do something with $line foo=bletch done < /etc/passwd echo "foo is now: $foo"儘管 "foo=bletch" 已經設定了 foo 的值,然而在多種系統的 Bourne shell 上執行此 script 的時候仍會印出 "foo is now: bar"。為什麼呢?因為一些 歷史因素,在 Bourne shell 當中,一個控制結構(如一個迴圈,或者一個 "if" 敘述)的重導向會造出一個新的 subshell,所以啦,在此 subshell 內 所設定的變數當然不會影響目前 shell 的變數。
POSIX 1003.2 Shell and Tools Interface 的標準委員會已防止上述的問題, 也就是上述的例子在遵循 P1003.2 標準的 Bourne shells當中會印出 "foo is now: bletch"。
在一些較古老的 (以及遵循 P1003.2 標準的) Bourne shell 當中,您可以使 用以下技巧來避免重轉向的問題:
foo=bar # make file descriptor 9 a duplicate of file descriptor 0 stdin); # then connect stdin to /etc/passwd; the original stdin is now # `remembered' in file descriptor 9; see dup(2) and sh(1) exec 9<&0 < /etc/passwd while read line do # do something with $line foo=bletch done # make stdin a duplicate of file descriptor 9, i.e. reconnect # it to the original stdin; then close file descriptor 9 exec 0<&9 9<&- echo "foo is now: $foo"這樣子不管在哪種 Bourne shell 應該都會印出 "foo is now: bletch"。 接下來,看看以下這個例子:
foo=bar echo bletch | read foo echo "foo is now: $foo"這個例子在許多 Bourne shell 內都會印出 "foo is now: bar",有些則會 印出 "foo is now: bletch"。為什麼呢?一般說來,一個 pipeline 裡面 的每一個部份都是在一個 subshell 中執行。但是有些系統的裡 pipeline 的最後一個如果是如 "read" 這類的內建指令,並不會另外造出一個 subshell。
POSIX 1003.2 對這兩種作法並沒有硬性規定要用哪一種。所以如果想寫 一個 portable 的 shell script 不應該依賴這兩種作法其中的一種。