使用exec

exec <filename命令會將stdin重定向到文件中. 從這句開始, 全部的stdin就都來自於這個文件了, 而不是標準輸入(一般都是鍵盤輸入). 這樣就提供了一種按行讀取文件的方法, 而且可使用sed和/或awk來對每一行進行分析.shell

使用exec重定向stdinbash

1 #!/bin/bash
2 # 使用'exec'重定向stdin. 
3
4
5 exec 6<&0 # 將文件描述符#6與stdin連接起來. 
6 # 保存stdin. 
7
8 exec < data-file # stdin被文件"data-file"所代替. 
9
10 read a1 # 讀取文件"data-file"的第一行. 
11 read a2 # 讀取文件"data-file"的第二行. 
12
13 echo
14 echo "Following lines read from file."
15 echo "-------------------------------"
16 echo $a1
17 echo $a2
18
19 echo; echo; echo
20
21 exec 0<&6 6<&-22 #  如今將stdin從fd #6中恢復, 由於剛纔咱們把stdin重定向到#6了, 
23 #+ 而後關閉fd #6 ( 6<&- ), 好讓這個描述符繼續被其餘進程所使用. 
24 #
25 # <&6 6<&-  這麼作也能夠. 
26
27 echo -n "Enter data "
28 read b1 # 如今"read"已經恢復正常了, 就是可以正常的從stdin中讀取.
29 echo "Input read from stdin."
30 echo "----------------------"
31 echo "b1 = $b1"
32
33 echo
34
35 exit 0

一樣的, exec >filename命令將會把stdout重定向到一個指定的文件中. 這樣全部命令的輸出就都會發送到那個指定的文件, 而不是stdout.spa

exec N > filename會影響整個腳本或當前shell. 對於這個指定PID的腳本或shell來講,從這句命令執行以後, 就會重定向到這個文件中, 然而 . . .N > filename只會影響新fork出來的進程, 而不會影響整個腳本或shell. rest

使用exec來重定向stdoutcode

1 #!/bin/bash
2 # reassign-stdout.sh
3
4 LOGFILE=logfile.txt
5
6 exec 6>&1 # 將fd #6與stdout連接起來. 
7 # 保存stdout. 
8
9 exec > $LOGFILE # stdout就被文件"logfile.txt"所代替了. 
10
11 # ----------------------------------------------------------- #
12 # 在這塊中全部命令的輸出都會發送到文件$LOGFILE中. 
13
14 echo -n "Logfile: "
15 date
16 echo "-------------------------------------"
17 echo
18
19 echo "Output of \"ls -al\" command"
20 echo
21 ls -al
22 echo; echo
23 echo "Output of \"df\" command"
24 echo
25 df
26
27 # ----------------------------------------------------------- #
28
29 exec 1>&6 6>&- # 恢復stdout, 而後關閉文件描述符#6. 
30
31 echo
32 echo "== stdout now restored to default == "
33 echo
34 ls -al
35 echo
36
37 exit 0

使用exec在同一個腳本中重定向stdin和stdoutblog

1 #!/bin/bash
2 # upperconv.sh
3 # 將一個指定的輸入文件轉換爲大寫. 
4
5 E_FILE_ACCESS=70
6 E_WRONG_ARGS=71
7
8 if [ ! -r "$1" ] # 判斷指定的輸入文件是否可讀? 
9 then
10 echo "Can't read from input file!"
11 echo "Usage: $0 input-file output-file"
12 exit $E_FILE_ACCESS
13 fi #  即便輸入文件($1)沒被指定
14 #+ 也仍是會以相同的錯誤退出(爲何?). 
15
16 if [ -z "$2" ]
17 then
18 echo "Need to specify output file."
19 echo "Usage: $0 input-file output-file"
20 exit $E_WRONG_ARGS
21 fi
22
23
24 exec 4<&0
25 exec < $1 # 將會從輸入文件中讀取. 
26
27 exec 7>&1
28 exec > $2 # 將寫到輸出文件中. 
29 # 假設輸出文件是可寫的(添加檢查?). 
30
31 # -----------------------------------------------32 cat - | tr a-z A-Z # 轉換爲大寫. 
33 # ^^^^^ # 從stdin中讀取. 
34 # ^^^^^^^^^^ # 寫到stdout上. 
35 # 然而, stdin和stdout都被重定向了. 
36 # -----------------------------------------------37
38 exec 1>&7 7>&- # 恢復stout.
39 exec 0<&4 4<&- # 恢復stdin.
40
41 # 恢復以後, 下邊這行代碼將會如預期的同樣打印到stdout上. 
42 echo "File \"$1\" written to \"$2\" as uppercase conversion."
43
44 exit 0

I/O重定向是一種避免可怕的子shell中不可訪問變量問題的方法.進程

避免子shellci

1 #!/bin/bash
2 # avoid-subshell.sh
3 # 由Matthew Walker所提出的建議. 
4
5 Lines=0
6
7 echo
8
9 cat myfile.txt | while read line; # (譯者注: 管道會產生子shell)
10 do {
11 echo $line
12 (( Lines++ )); #  增長這個變量的值
13 #+ 可是外部循環卻不能訪問. 
14 #  子shell問題. 
15 }
16 done
17
18 echo "Number of lines read = $Lines" # 0
19 # 錯誤!
20
21 echo "------------------------"
22
23
24 exec 3<> myfile.txt
25 while read line <&3
26 do {
27 echo "$line"
28 (( Lines++ )); #  增長這個變量的值
29 #+ 如今外部循環就能夠訪問了. 
30 #  沒有子shell, 如今就沒問題了. 
31 }
32 done
33 exec 3>&-34
35 echo "Number of lines read = $Lines" # 8
36
37 echo
38
39 exit 0
相關文章
相關標籤/搜索