Chinaunix首页 | 论坛 | 博客
  • 博客访问: 15531038
  • 博文数量: 2005
  • 博客积分: 11986
  • 博客等级: 上将
  • 技术积分: 22535
  • 用 户 组: 普通用户
  • 注册时间: 2007-05-17 13:56
文章分类

全部博文(2005)

文章存档

2014年(2)

2013年(2)

2012年(16)

2011年(66)

2010年(368)

2009年(743)

2008年(491)

2007年(317)

分类:

2008-12-23 22:35:54

exec 命令会将stdin重定向到文件中. 从这句开始, 所有的stdin就都来自于这个文件了, 而不是标准输入(通常都是键盘输入). 这样就提供了一种按行读取文件的方法, 并且可以使用和/或来对每一行进行分析.


例子 16-1. 使用exec重定向stdin

  1 #!/bin/bash
2 # 使用'exec'重定向stdin.


5 exec 6<&0 # 将文件描述符#6与stdin链接起来.
6  # 保存stdin.

8 exec < data-file # stdin被文件"data-file"所代替.

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.

Important

exec N > filename会影响整个脚本或当前shell. 对于这个指定的脚本或shell来说, 从这句命令执行之后, 就会重定向到这个文件中, 然而 . . .

N > filename只会影响新fork出来的进程, 而不会影响整个脚本或shell. not the entire script or shell.

感谢你, Ahmed Darwish, 指出这个问题.


例子 16-2. 使用exec来重定向stdout

  1 #!/bin/bash
2 # reassign-stdout.sh

4 LOGFILE=logfile.txt

6 exec 6>&1 # 将fd #6与stdout链接起来.
7  # 保存stdout.

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


例子 16-3. 使用exec在同一个脚本中重定向stdinstdout

  1 #!/bin/bash
2 # upperconv.sh
3 # 将一个指定的输入文件转换为大写.

5 E_FILE_ACCESS=70
6 E_WRONG_ARGS=71

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重定向是一种避免可怕的问题的方法.


例子 16-4. 避免子shell

  1 #!/bin/bash
2 # avoid-subshell.sh
3 # 由Matthew Walker所提出的建议.

5 Lines=0

7 echo

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
40 
41 # 下边这些行是这个脚本的结果, 脚本是不会走到这里的.
42 
43 $ cat myfile.txt
44 
45 Line 1.
46 Line 2.
47 Line 3.
48 Line 4.
49 Line 5.
50 Line 6.
51 Line 7.
52 Line 8.

阅读(3957) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~